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.,

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;
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 ;-)


In reply to Re: object method question by Tanktalus
in thread object method question by Zarathustra

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.