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

Hi Monks,

I have posted this as a comment at "Re: my $self is stumped!". One Monk suggested to discuss it as a new post. So I am posting it again. Please refer to "my $self is stumped!" for original question to which I commented, for a clear picture.

We use the code  $self->SUPER::introduce();to call introduce() of package person. Unlike Java or other Object Oriented Languages, 'SUPER' is not an object or reference to the instance of parent. The 'SUPER' just make the parser to look into @ISA for packages containing the method 'introduce()'

In the very basics of perl Object Orientations itself, we learn that in $obj->method(), $obj is the 1st argument to function 'method()'. In case of  $self->SUPER::introduce();we can see that function is ' SUPER::introduce() ' and NOT' introduce() '. Also, the object passed is  ' $self ' and NOT  ' $self->SUPER '. For 'real' Object Oriented designs, don't we need ' SUPER ' as an object or reference to the instance of base classes(s). (I know there are some limitations)

Here the question is "How the child (object) know its parent(object)" and NOT "Parent knowing the child"

Hello Monks, Can you help us to solve this problem, other than creating instance of base classes inside our package?

--VC

Replies are listed 'Best First'.
Re: SUPER in OOPerl is dumped with $self
by dsheroh (Monsignor) on Jul 03, 2007 at 16:02 UTC
    Here the question is "How the child (object) know its parent(object)" and NOT "Parent knowing the child"

    In general, the answer (regardless of language) is "there is no general answer". OO is about the relationships of classes to each other, specifically "is-a" relationships in the case of inheritance. If the objects are also related (which they may or may not be), you have to set up some form of references from one to the other to create that relationship as it's not an inherent part of OO.

    The example in the other thread confuses the issue because it defines a parent class (person) which is intended to represent a mother and a child class (child) which is intended to represent her son. The differences between the OO parent/child relationship ("a child is a person") and the real-world parent/child relationship ("Billy is Alice's son") make it difficult to discuss clearly.

    If we take a different set of classes, say Vehicle and Truck, then it is more obvious that "a Truck is a Vehicle" without the implications that any individual truck (instance) has a parent (instance). (And, if it did, its "parent" would be either a Factory or a Person::AutoDesigner, not a Vehicle.)

    Can you help us to solve this problem, other than creating instance of base classes inside our package?

    I still don't see what the problem is. As I asked in the other thread, "what is it that you want to accomplish without creating instances of base classes inside your package?" If you're creating instances of the base class, then that suggests to me that you're thinking of the base class and derived class as two different things (Billy and Alice, in the original example) and, if that's the case, then they should be instantiated as two separate objects rather than trying to trick one object into doing double duty.

Re: SUPER in OOPerl is dumped with $self
by pajout (Curate) on Jul 03, 2007 at 09:42 UTC
    Could you, please, explain some situation, when some object needs to "know" its parent? Perhaps I am stupid, but I cannot imagine situation, when SUPER is not enough...

      Hi Monks,

      The code in question was there at node my $self is stumped!. I am pasing the code below for your reference.

      How do I get the parent method to call the parent second method? #!/usr/bin/perl use strict; package person; sub new { my $class = shift(@_); my $self = { 'name' => 'Alice' }; bless($self, $class); return($self); } sub tellName { my($self)=$_[0]; print "$self->{'name'}.\n"; } sub introduce { my($self)=$_[0]; print "Hello, I'm "; $self->tellName(); } 1; package child; our @ISA = qw(person); # inherits from person sub new { my $class = shift(@_); my $self = $class->SUPER::new(); $self ->{'nickName'} = 'Billy The Kid'; bless $self, $class; return $self; } sub tellName { my($self)=$_[0]; print "$self->{'nickName'}.\n"; } sub introduce { my($self)=$_[0]; print "Hi, I'm "; $self->tellName(); print "Here's my mom: "; $self->SUPER::introduce(); } 1; package main; my $mom = new person(); $mom->introduce(); # that time it works. print "\n"; my $son = new child(); $son->introduce();

      When the child calls the parent method with $self->Super::firstmethod(), the parent method uses $self->secondmethod(). But the secondmethod() that gets called is the over-ride version, because $self is a reference to to the child object.

        Consider situation, when you create $mom1, $mom2, $son1 and $son2 in your main package. That sons cannot know anything about their parent objects without explicit setting this relation. According to OO conception, they inherit from classes, not from objects (instantiated classes).

        My opinion is that it is not possible in your example, but you require something not compliant with OO.

        I see only this way:

        sub parent { my($self, $parent) = @_; $$self{parent} = $parent if defined $parent; return $$self{parent} }
        Update: Or, to allow unsetting of parent:
        sub parent { my($self, $parent) = @_; $$self{parent} = $parent if 1 < @_; return $$self{parent} }
        But the secondmethod() that gets called is the over-ride version, because $self is a reference to to the child object.

        Which is exactly as it should be - that's the nature of polymorphism.

        This isn't anything unique to Perl. Shortly after reading the original thread, I talked to a friend who's a Java programmer. He's been writing Java more-or-less exclusively for as long as I've known him (we met in 1999) and never touched Perl in his life. When I told him about the original post and that child::tellName was called instead of person::tellName, his exact reply was, "And that surprised him?"

        If you want to ignore polymorphism and have person::introduce always call person::tellName instead of any overridden version, then change the call in person::tellName from $self->tellName(); (which calls any overrides which may be in place for $self's class) to person::tellName($self); (which always calls person's version regardless of $self's class). I've already posted a revised version of the sample code which demonstrates this in the other thread at Re^4: my $self is stumped!.