srdst13 has asked for the wisdom of the Perl Monks concerning the following question:

I thought I pretty much understood inheritance, but I am missing something in my latest attempt. I am trying to make a simple class that inherits from DBIx::SQLEngine. I have not attempted to add any methods, just to implement a new() method in MY class that generates an object that @ISA DBIx::SQLEngine. I keep getting an error that looks like I am not actually inheriting any methods from DBIx::SQLEngine. Here is the simple module code (and made change to call to SUPER::new() directly--thanks frodo72):

package Bio::DB::UCSC::DB; use strict; use DBIx::SQLEngine; our @ISA = qw/DBIx::SQLEngine/; sub new { my $proto = shift; my $class = $proto; my $self = $class->SUPER::new(@_); bless($self, $class); return($self); } 1;
And here is a little test script, debugger output, and error message:
#!/usr/bin/perl use strict; use Bio::DB::UCSC::DB; use DBIx::SQLEngine; my $db = Bio::DB::UCSC::DB->new('dbi:mysql:database=hg18','uname','pas +swd'); my $sqldb = DBIx::SQLEngine->new('dbi:mysql:database=hg18','uname','pa +sswd'); my $refGenes1 = $sqldb->fetch_select( tables => {'refGene.name' => 'refLink.mrnaAcc'}, where => ['refGene.name like ?','NM_0002%']); my $refGenes = $db->fetch_select( tables => {'refGene.name' => 'refLink.mrnaAcc'}, where => ['refGene.name like ?','NM_0002%']);
From the debugger, I dump out the $db and $sqldb objects, which look like:
DB<3> x $sqldb 0 DBIx::SQLEngine::Driver::Mysql::V3_0=HASH(0x1a7c478) 'dbh' => DBI::db=HASH(0x1a28f78) empty hash 'package' => 'DBIx::SQLEngine::Driver' 'reconnector' => CODE(0x1a7c4a8) -> &DBIx::SQLEngine::Driver::__ANON__[/Library/Perl/5.8.1/DBIx/S +QLEngine/Driver.pm:252] in /Library/Perl/5.8.1/DBIx/SQLEngine/Driver. +pm:252-252 DB<4> x $db 0 Bio::DB::UCSC::DB=HASH(0x1a28f54) 'dbh' => DBI::db=HASH(0x15c1fb8) empty hash 'package' => 'DBIx::SQLEngine::Driver' 'reconnector' => CODE(0x1a29938) -> &DBIx::SQLEngine::Driver::__ANON__[/Library/Perl/5.8.1/DBIx/S +QLEngine/Driver.pm:252] in /Library/Perl/5.8.1/DBIx/SQLEngine/Driver. +pm:252-252
So, they look OK, but I get an error when I try to use the $db object:
main::(test.pl:16): my $refGenes = $db->fetch_select(tables => {'r +efGene.name' => 'refLink.mrnaAcc'}, main::(test.pl:17): where => ['re +fGene.name like ?','NM_0002%']); DB<1> Can't locate object method "fetch_select" via package "Bio::DB::UCSC:: +DB" at test.pl line 16. at test.pl line 16 Debugged program terminated. Use q to quit or R to restart,

Any hints are appreciated.

Thanks,
Sean

Replies are listed 'Best First'.
Re: Inheritance confusion
by polettix (Vicar) on Aug 08, 2006 at 16:43 UTC
    Please make it clear when you make changes to your posts (a SUPER suddenly popped up ;).

    The fact is that the new class method in:

    my $self = $class->SUPER::new(@_);
    does not give back a DBIx::SQLEngine object, but a DBIx::SQLEngine::Driver::Mysql::V3_0 one as you can see from the debugger:
    DB<3> x $sqldb 0 DBIx::SQLEngine::Driver::Mysql::V3_0=HASH(0x1a7c478) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    I suspect that the fetch_select method is actually present in this latter class, not in the frontend DBIx::SQLEngine, hence the problems. Are you sure that the DBIx::SQLEngine is intended for subclassing?

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Don't fool yourself.

      I don't know whether or not it is meant to be subclassed--there is no mention that it is, so quite possibly not. If it returns a blessed hash, shouldn't I be able to bless that into my own class? Or is there more to it than that? I looked through perltoot again; there is plenty of discussion of making your own classes, but it doesn't answer the question of exactly what needs to happen to be heritable.

      Finally, thanks for the $class->SUPER::new() correction. In my frustration, I had changed the code to the unintelligible form that I originally posted.

      Sean

        Hey. It sounds like it is a factory. As such it returns a different object type, not its own. You should be able to rebless this, but you'll have to change your ISA to refelct the actual parent instead of the factory. Maybe you can dynamicaly find out the object you recieves type, then add that to the ISA and rebless yours? This would be a problem if you use your factory to create more than one type of object. I don't think perl supplies a way for each object to store its own class info like some sort of anonymous class....i bet perl6 does though ;)

        All information in the post is suspect to error as i'm just guessing here


        ___________
        Eric Hodges
        I'm really too lazy to dwelve into the inheritance tree of DBIx::SQLEngine, but the bottom line is probably that you're inheriting from one class but the $self you get belongs to a different one. As eric256 suggests you could cope with some run-time modification of @ISA, in order to include the real class of $self, e.g.:
        sub new { my $class = shift; my $self = DBIx::SQLEngine->new(@_); no strict 'refs'; push @{$class . '::ISA'}, ref $self; return bless $self, $class; }
        Before you decide to take this path be sure to read this thread!

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.