in reply to my $self is stumped!

Hi Monks,

Here we cant just blame $self. We need to think of few facts.

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)

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^2: my $self is stumped!
by dsheroh (Monsignor) on Jun 22, 2007 at 16:32 UTC
    I'm not sure I agree with your definition of "'real' Object Oriented designs". Many (perhaps even most) OO languages don't treat classes as objects themselves. How, then, can SUPER (or its equivalent) be provided as an object when it isn't one? How can it provide a reference to an instance of a base class which is not instantiated (or which instance should be used if there are several)?

    Perl makes a firm (though not completely hard) division between objects and classes. I've also worked with languages that make no distinction - all classes are objects and all objects are classes - and can't remember ever running into anything that can be done in one style but not the other.

    So what is it that you want to accomplish without creating instances of base classes inside your package? (Probably best to answer in a new post instead of as a comment on this one, though...)

      If I understand it right, in C++, which is where I first learned OOP, instantiating a child object always instantiates a complete object of the base class as well. All of the base class data members and methods are availabe, even if they are overidden by the child.

      The problem that I started with is one that I've never had in C++ (or python as far as I recall). That doesn't mean that perl is "bad" or anything. Just different. I see that there is a different approach to OO in perl than C++. Nothing wrong with different, per se.

      I like all the interesting ideas presented in these solutions. But I didn't use any of them. Most of them require the parent to have some knowledge of the children that may inherit from it. Which is a big OO no-no in my opinion.

      What I ended up doing was replicating some of the parent method's functionality in the child method. This is something that I shouldn't have to do. That's part of the point of inheritance to re-use that code. But I find that with perl, its easier to do that than to go through shenannigans to access parent methods of a parent object that is never actually instantiated...

      Thanks for your many replies. it has been a learning experience, and I will continue to follow the thread and I will return to perl-monks now that I have found such a great community!

        I agree that it's a big no-no to require the parent to have any knowledge of the child and that you shouldn't have to replicate functionality. But I also think that you brought the shenanigans on yourself by not maintaining a clear distinction between classes and instances (at least in the provided sample code; this problem may be an artifact of the sample rather than something present in your real project) - not all (non-child) people are named Alice, so that name should not be hardcoded in the class. Nor are all children named Billy the Kid. A child and its mother are two distinct people, therefore they should be instantiated as two distinct objects and one should refer to the other rather than trying to roll both into a single object.

        Here's a slightly modified version of your original code which doesn't require either class to have any information about the internals of the other, doesn't replicate functionality from one class in the other, doesn't require any shenanigans, and maintains a clear distinction between classes and instances. I've also added in Billy's father to clarify that Alice (the instance) is distinct from person (the class). And Billy introduces himself twice, once via person's tellName and once via child's tellName, to show how to force the parent class's methods to call each other while maintaining encapsulation and avoiding duplicate code.

        #!/usr/bin/perl use strict; package person; sub new { my $class = shift(@_); #my $self = { 'name' => 'Alice' }; my $self = { 'name' => shift }; 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(); person::tellName($self); } 1; package child; our @ISA = qw(person); # inherits from person sub new { my $class = shift(@_); #my $self = $class->SUPER::new(); my $self = $class->SUPER::new(shift); #$self ->{'nickName'} = 'Billy The Kid'; $self ->{'nickName'} = shift; $self->{mom} = shift; $self->{dad} = shift; bless $self, $class; return $self; } sub tellName { my($self)=$_[0]; print "$self->{'nickName'}.\n"; } sub introduce { #my($self)=$_[0]; print "Hi, I'm "; my($self)=$_[0]; $self->SUPER::introduce(); print 'but they also call me '; $self->tellName; print "Here's my mom: "; #$self->SUPER::introduce(); $self->{mom}->introduce; print "Here's my dad: "; $self->{dad}->introduce; } 1; package main; my $mom = new person('Alice'); my $dad = person->new('Charlie'); $mom->introduce(); # that time it works. $dad->introduce; print "\n"; my $son = new child('Billy', 'Billy the Kid', $mom, $dad); $son->introduce();

        It produces the output:

        Hello, I'm Alice. Hello, I'm Charlie. Hello, I'm Billy. but they also call me Billy the Kid. Here's my mom: Hello, I'm Alice. Here's my dad: Hello, I'm Charlie.