Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Simple inheritance question

by halfcountplus (Hermit)
on Apr 23, 2010 at 16:03 UTC ( #836551=perlquestion: print w/ replies, xml ) Need Help??
halfcountplus has asked for the wisdom of the Perl Monks concerning the following question:

How can I inherit a method, in this example, test():
#!/usr/bin/perl -w use strict; { package One; sub test { my $x = pop; print "$x\n"; } } { package Two; use base "One"; sub new { my $self = {}; bless($self); } sub eg { test(pop); } } my $obj = new Two(); $obj->eg("hello");
I know "One->test()" will work, it just seems strange to me that I could then use $obj->test(), but not test() in Two's definition.

Comment on Simple inheritance question
Download Code
Re: Simple inheritance question
by webfiend (Vicar) on Apr 23, 2010 at 16:19 UTC

    The main problem here is that you don't have a constructor for package One, so there's nothing for package Two to inherit. There are a lot of other little things with the code (like the fact that test() is a simple sub rather than a method, for example) which suggest the Perl OO tutorial perltoot might be a good item for you to read for a handle on how objects are handled in Perl.

    Edit: I answered the wrong question and with an inaccurate answer. Then again, I learned something new about Perl and how it handles inheritance, so it wasn't a total loss.

      Adding a constructor to One does not make any difference. Would have been nice if you could have named those "little things" since I have already read the man page, and all of "Intermediate Perl" (the OO book).

      AFAICT it simply isn't possible to call a method from One in Two without using a class prefix. Simple confirmation of this (from someone who knows) will suffice, using One::test() instead of test() is fine, it just seems slightly silly, since One inherited Two's methods.
        Would have been nice if you could have named those "little things"

        That's a fair point. Here's a modified version of the code doing what I think you might have been trying to do. I'm also realizing I may have misread the question, but I've got momentum now. Might as well paste what I have.

        #!/usr/bin/perl # Use the warnings pragma rather than the -w flag use warnings; use strict; { package One; # Define a constructor for One sub new { my $class = shift; # Constructors need to know what class they +'re for my $self = {}; bless($self, $class); # Tell Perl what $self is being blessed +into } sub test { my $self = shift; # Is this an object method? Better grab $sel +f my $x = pop @_; # I usually shift from the argument list, but +whatever # Also, I like to be explicit about what I'm # popping/shifting from print "$x\n"; } } { package Two; use base "One"; # Two::new didn't add anything to One, so I removed it. sub eg { my $self = shift; # Is this an object method? Better grab $se +lf my $arg = pop @_; # pop() again? Okay, break it out and make +it explicit. $self->test($arg); # Is test() an object method? I'll use it a +s if it was. } } my $obj = new Two(); $obj->eg("hello");

        Edit: Incidentally, I think jethro has the solution you're looking for. I've become so used to making everything explicit by spelling out object or module connections that I didn't even think of Exporter.

Re: Simple inheritance question
by jethro (Monsignor) on Apr 23, 2010 at 16:29 UTC
    If test() were included in Two's namespace, Two could not override it with its own test() if needed.

    UPDATE: You can use Exporter to add test to Two's namespace if you like. After all a class is just a package

      Yeah, that does it:
      #!/usr/bin/perl -w use strict; { package One; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(test); sub test { my $x = pop; print "$x\n"; } } { package Two; use base "One"; sub new { One->import; my $self = {}; bless($self); } sub eg { test(pop); } } my $obj = new Two(); $obj->eg("hello");
      Thanks all!
Re: Simple inheritance question
by ikegami (Pope) on Apr 23, 2010 at 16:51 UTC

    Perl has no idea it's suppose to call test as a method.

    The only difference between a function and a method is how the sub is called, or rather, how it expects to be called.

    test() # function Module::test() # function $obj->test() # virtual instance method $class->test() # static method

    Non-virtual instance methods can be approximated using

    test($obj) # From within the object that defines test(). -or- Class::test($obj) # From anywhere.

    I say "approximate", since it's doesn't check inheritance.

    And there's also this syntax:

    $obj->Class::test() $class->Class::test() $obj->SUPER::test() $class->SUPER::test()

    In this case, all of the following work:

    sub eg { $_[0]->test($_[1]); } sub eg { One::test(@_); } sub eg { Two->test($_[1]); } sub eg { One->test($_[1]); }

    Only the first really makes sense, though. And maybe the second one if you don't want test to be overridden by a child class of Two.

Re: Simple inheritance question
by nvivek (Vicar) on Apr 24, 2010 at 09:34 UTC

    In the eg subroutine,you have to call the test subroutine by in the following two ways.

    $_[0]->test(pop); #Here $_[0] contains the class name. #first interpreter will check test is defined in Two or not. #If it isn't defined,then it will check the method in One package beca +use of use base function One::test(pop); #calling the test method using the class name One beca +use test isn't in Two's package workspace

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://836551]
Approved by moritz
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2014-12-25 15:23 GMT
Find Nodes?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?

    Results (160 votes), past polls