Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Failing inheritance or what can make a Child disinherited ?

by guha (Priest)
on Aug 02, 2004 at 18:16 UTC ( [id://379356]=perlquestion: print w/replies, xml ) Need Help??

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

I am writing tests for a module Child which inherits from Parent, and have run into a oddity which I can't grasp.

These modules are part of a larger framework and it is pretty difficult to strip it down to a non-working snippet of code.

However these are the facts before the crime:

my $o = Child->new; print ref($o); #Child print $o->isa('Child'); # 1 print $o->isa('Parent'); # 1 print join(':', @Child::ISA) # Parent my $method = 'testSign'; my $code = $o->can($method); print $code; # CODE(0x20d5b94)

Either of

$o->$method()
or
$o->$code()

emits the following error
Undefined subroutine &ClientChild::testSign called at program.t line nnn.

The testSign method is only defined in the Parent class.

So whats going on, to me it looks like inheritance does not occur even though the prerequsites seem fulfilled.

Hints, ptrs, wild shots in the dark greatly appreciated!

perl -v #AS-635

update: Thanks adrianh & ysth for spotting my transcription error.

Sort of Solved:Added a method Fubar to Parent. And tested with that, and now it worked. So obviously there was something special with the testSign name. A little searching revealed the testSign was referenced in Child like so

my %_init_mems = ( Password => \&testPassword, Sign => \&testSign, Name => \&testNameX2, Titel => \&testStrX, );

I'm not sure but does this act as a declaration for sub testSign in Child namespace ala ysth's and Ovid's suggestions?

But in that case the testSign in Child ought to have been invoked as a method instead ?

Replies are listed 'Best First'.
Re: Failing inheritance or what can make a Child disinherited ?
by ysth (Canon) on Aug 02, 2004 at 20:36 UTC
    Good job tracking this down! Yes, taking a reference to an undefined sub does create a "declaration". And a method call to a declared but undefined sub does fail like:
    $ perl -we'sub foo; my $obj = bless {}, "main"; $obj->foo()' Undefined subroutine &main::foo called at -e line 1.
    It doesn't give the same error as
    $ perl -we'my $obj = bless {}, "main"; $obj->foo()' Can't locate object method "foo" via package "main" at -e line 1.
    because the method is located; it's just not defined.
Re: Failing inheritance or what can make a Child disinherited ?
by dragonchild (Archbishop) on Aug 02, 2004 at 18:23 UTC
    I'm surprised $o->$method doesn't work, as I use it extensively. What's your OS/Perl version?

    You might have to do $code->($o) to make the coderef work.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      WinXp/AS635

      Yeah, $o->$method and the other two variations work in other programs. It also works well in the test script I wrote to exercise the "feature" ;-/

Re: Failing inheritance or what can make a Child disinherited ?
by Ovid (Cardinal) on Aug 02, 2004 at 19:13 UTC

    Is there any chance that you have more than one definition of the base or child class? If so, could you possibly be using a module different from the one you think you are using?

    Also, how is testSign being called? If it's called with function syntax instead of method syntax, you'll get the error described.

    Cheers,
    Ovid

    New address of my CGI Course.

      Several good ideas!

      Calling testSign directly as a subroutine works

      print &Parent::testSign() # 1 eq OK

      Showing that the subroutine/method is defined in Parent, but the method invocation does not dispatch to Parent.

Re: Failing inheritance or what can make a Child disinherited ?
by ysth (Canon) on Aug 02, 2004 at 18:52 UTC
    Is "Client" Parent, Child, or neither? Do you have any AUTOLOAD routines? Any declarations like "sub testSign;"? What's @Parent::ISA?
      s/Client/Child/;

      No AUTOLOAD

      No declarations

      print join(':', @Parent::ISA) # aka empty
        With:
        $code = $obj->can("testSign");
        What does $code->($obj) do? What does use Devel::Peek; Dump $code; show? (Grasping at straws.)
Re: Failing inheritance or what can make a Child disinherited ?
by adrianh (Chancellor) on Aug 02, 2004 at 18:54 UTC
    Undefined subroutine &Client::testSign called at program.t line nnn.

    Client::testSign?

Re: Failing inheritance or what can make a Child disinherited ?
by shemp (Deacon) on Aug 02, 2004 at 19:43 UTC
    Based on your error message:

    Undefined subroutine &Child::testSign called at program.t line nnn.

    I would have to say that you are NOT calling it as a method. When i try calling a non-existant method, i get an error like:

    Can't locate object method "junk" via package PACKAGE_NAME

      Couldn't agree more with you, this is I think the real indicator of a serious problem as I AM calling with different variations of method invocation "->"

      The error message you indicate would be more normal, showing signs of dispatch mechanism not finding the requested method

        Not too long ago i created this piece of code to try to help with some debugging. It should tell you the entire ancestor tree of your object. I dont think the order is exactly like the way that methods would be searched for, but i thought of this code when i first read your post.

        Put this method in your Child class. (hopefully you'll be able to call it.)

        sub isa_descent { my $self = shift @_; my ($class) = @_; print "\npackage: $class\n"; no strict 'refs'; my @ancestors = @{ 'main::' . $class . '::ISA' }; use strict; foreach my $ancestor ( @ancestors ) { print "...ancestor: $ancestor\n"; $self->isa_descent($ancestor); } }
        You'll want to call it from outside the class probably, perhaps just after creating the object instance. The output wont change unless you're messing with @ISA.
        $o->isa_descent(ref $o);
Re: Failing inheritance or what can make a Child disinherited ?
by gaal (Parson) on Aug 02, 2004 at 18:21 UTC
    Wild shot: what does

    $code->();

    do?

      Same error as above.

Re: Failing inheritance or what can make a Child disinherited ?
by shemp (Deacon) on Aug 02, 2004 at 19:08 UTC
    Are you possibly mistakenly assigning something else to $code (even indirectly) at some intermediate point?

    Also, what happens when you call testSign directly?

    $o->testSign();
    Vert, very, very strange!
      Vert, very, very strange!

      Agreed!

      And no the direct call, dies with the same error.

Re: Failing inheritance or what can make a Child disinherited ?
by pbeckingham (Parson) on Aug 02, 2004 at 18:58 UTC

    Although I have no clue what is wrong, nor do I have anything to offer as a solution, for which I am sorry, I must say that this is a very well-presented question. That they were all this well put...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://379356]
Approved by chromatic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-04-20 01:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found