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

OK create 3 modules A, B & C in 3 separate files all in the same directory like so: A.pm:
package A; sub foo { print "xyzzy\n"; } 1;
B.pm:
package B; use base 'A'; 1;
and C.pm:
package C; use base 'B'; 1;
and now set up a 'test.pl':
#!/usr/bin/perl require 'C.pm'; C::foo();
Run it and you get:

22. perl test.pl
Can't locate object method "foo" via package "C" at C.pm line 5.

Why doesn't it find the sub foo in 'A.pm'? I must be making a newbie mistake, but for the life of me I can't see what.

Replies are listed 'Best First'.
Re: Inheritance strangeness
by Joost (Canon) on Sep 08, 2004 at 07:58 UTC
Re: Inheritance strangeness
by Zaxo (Archbishop) on Sep 08, 2004 at 07:57 UTC

    Do $ perl -e'print "@INC"' from the command line to see whether the core lib location or '.' (dot) is searched first. B is perl's core backend module, and doesn't have a foo() function.

    After Compline,
    Zaxo

Re: Inheritance strangeness
by BUU (Prior) on Sep 08, 2004 at 07:49 UTC
    The mistake is simple. Bar::foo() just tries to call the function foo() from package Bar. If you want to call an inherited method, you must use the class method call: Bar->foo()
      Change test.pl to
      #!/usr/bin/perl require 'C.pm'; C->foo();
      and you get:

      55. perl test.pl
      Can't locate object method "foo" via package "C" at test.pl line 5.

        Watch for the bold
        C:\e>echo package A;sub foo{666};1; >A.pm
        
        C:\e>echo package B;use base 'A';1; >B.pm
        
        C:\e>echo package C;use base 'B';1; >C.pm
        
        C:\e>perl -e"require 'C.pm';die C->foo()"
        Can't locate object method "foo" via package "C" at -e line 1.
        
        
        C:\e>perl -le"require 'C.pm';print for %INC"
        XSLoader.pm
        C:/Perl/lib/XSLoader.pm
        Carp.pm
        C:/Perl/lib/Carp.pm
        warnings/register.pm
        C:/Perl/lib/warnings/register.pm
        Exporter.pm
        C:/Perl/lib/Exporter.pm
        vars.pm
        C:/Perl/lib/vars.pm
        strict.pm
        C:/Perl/lib/strict.pm
        C.pm
        C.pm
        warnings.pm
        C:/Perl/lib/warnings.pm
        base.pm
        C:/Perl/lib/base.pm
        B.pm
        C:/Perl/lib/B.pm
        
        C:\e>

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

        This does what you'd expect:

        use C; C->foo();

        Update: In my test code, I had a use lib "[directory with A.pm, B.pm, C.pm]" before use C;. That means I explicitly got the new B.pm instead of the system one. Everyone else is right that if you're picking up the system B.pm first, that's a problem.

Re: Inheritance strangeness
by cleverett (Friar) on Sep 08, 2004 at 08:07 UTC
    Damn,

    I tried to make simple test case for a problem I'm having with mod_perl spread out over 5 modules and using multiple inheritance, and I ran into the stupid B module.

    The test case now works, but my mod_perl issue still exists ... Grr!

      And the same answer as above applies...

      C::foo is a function call, C->foo is a method call.

      C::foo is procedural style and doesn't inherit, C->foo is an OO style and does inherit.
Re: Inheritance strangeness
by cleverett (Friar) on Sep 08, 2004 at 07:48 UTC
    Whoops I meant:

    run it and you get:

    53. perl test.pl
    Undefined subroutine &C::foo called at test.pl line 5.