in reply to object method question
In general, I think I would subclass from the other object, and add in the functions I want to the subclass. In your specific example with DBI, I think that will be royally difficult to do. You may be better off just telling the users to call $foo->dbq rather than $foo->get_dbh->dbq.
It is possible in perl to affect other packages' inheritance (that's what base does). It's a bad idea in general unless you're asking someone else to affect your tree (DBI won't be asking you to affect its tree). And with DBI, it's even worse since there aren't any actual DBI objects floating around - DBI->connect is just a factory function for finding the right DBD driver, loading it, and instantiating it with the connection string.
I'm curious, however, as to why you feel you need to be able to call dbq from the dbh object rather than from the foo object. Currently existing code won't know about the new dbq function they could ask for from the db handle, only new code could be aware of it, so if you just pass in $foo instead of $dbh, then you're all set - call $foo->dbq for your queries, and $foo->get_dbh for anything else.
The alternate design that may work takes up a fair bit more time, IMO. Not runtime time, but developer time, which is a much more precious commodity most of the time. You could write a wrapper object that HASA $dbh handle (or HASA $foo handle), and an AUTOLOAD which would redirect unknown functions (such as execute or prepare) to the $dbh (or $foo->dbh). Then you could have get_dbh return this object instead, and most users wouldn't be able to tell the difference. e.g.,
Then, instead of returning $self->{_dbh}, you return Foo::DBIWrapper->new($self->{_dbh}). A bit more work, and it does make things just a wee bit more entertaining to debug, and there are lots of AUTOLOAD horror stories to be concerned with (throws UNIVERSAL::can for loops, for example, doesn't inherit very nicely, etc.), but if you're careful, and you know what you're doing, it should work. Perl does make this a bit easier than other languages ;-)package Foo::DBIWrapper; use strict; sub new { my $class = shift; my $dbh = shift; my $self = { _dbh => $dbh }; bless $self, $class; } sub dbq { my $self = shift; my $sql = shift; my $sth = $self->prepare($sql); # don't use the _dbh! $sth->execute(@_); # added @_ for any binding return $sth; } our $AUTOLOAD; sub AUTOLOAD { my $self = shift; (my $func = $AUTOLOAD) =~ s/.*:://; if (my $coderef = $self->{_dbh}->can($func)) { unshift @_, $self; goto &$coderef; } die "Can't $AUTOLOAD in $self"; } 1;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: object method question
by jZed (Prior) on Oct 11, 2005 at 03:03 UTC | |
by Zarathustra (Beadle) on Oct 11, 2005 at 06:52 UTC | |
|
Re^2: object method question
by Zarathustra (Beadle) on Oct 11, 2005 at 03:09 UTC | |
|
Re^2: object method question
by BUU (Prior) on Oct 11, 2005 at 21:00 UTC | |
by Tanktalus (Canon) on Oct 11, 2005 at 21:45 UTC | |
by BUU (Prior) on Oct 12, 2005 at 02:38 UTC |