OOP: Inheriting identically named methods

T

Tore Aursand

Hmm. Don't know if I got the subject totally right. Just take a look at
the example instead.

I'm having problems with simple OOP inheritance. Seems like I've been
away from the OOP business too long. I've read through perlboot, perltoot
and perltooc.

Here's some sample code:

package Person;
use strict;
use warnings;

sub new {
my $class = shift;

my $self = {
'firstname' => '',
'lastname' => '',
'age' => 0,
};
bless( $self, $class );

$self->_init( @_ );

return $self;
}

sub _init {
my $self = shift;
my %ARGS = @_;

$self->{'firstname'} = $ARGS{'firstname'} || '';
$self->{'lastname'} = $ARGS{'lastname'} || '';
$self->{'age'} = $ARGS{'age'} || 0;
}

1;

package Employee;
use strict;
use warnings;

use Person;
our @ISA = qw( Person );

sub new {
my $class = shift;

my $self = $class->SUPER::new( @_ );
$self->{'salary'} = 0;
bless( $self, $class );

$self->_init( @_ );

return $self;
}

sub _init {
my $self = shift;
my %ARGS = @_;

$self->{'salary'} = $ARGS{'salary'} || 0;
}

1;

This code may very well work as intended, but when I create a new instance
of the Employee class, only Employee::_init() is run (and it is run twice);

#!/usr/bin/perl
#
use strict;
use warnings;

use Employee;

my $Employee = Employee->new();

I really thought this would spawn into this:

Employee::new()
Person::new()
Person::_init()
Employee::_init()

But it doesn't. Instead it is executed in this manner:

Employee::new()
Person::new()
Employee::_init()
Employee::_init()

Anyone care to explain what's going on and what I need to do in order to
make this work as I want it to?

Thanks!
 
B

Ben Morrow

Tore Aursand said:
Hmm. Don't know if I got the subject totally right. Just take a look at
the example instead.

I'm having problems with simple OOP inheritance. Seems like I've been
away from the OOP business too long. I've read through perlboot, perltoot
and perltooc.

Here's some sample code:

package Person;
use strict;
use warnings;

sub new {
my $class = shift;

my $self = {
'firstname' => '',
'lastname' => '',
'age' => 0,

You don't need to do this as you init them all in _init. You can just
say
my $self = bless {}, $class;
};
bless( $self, $class );

$self->_init( @_ );

If $self is actually an Employee object, this will call Employee::_init.
return $self;
}

sub _init {
my $self = shift;
my %ARGS = @_;

$self->{'firstname'} = $ARGS{'firstname'} || '';
$self->{'lastname'} = $ARGS{'lastname'} || '';
$self->{'age'} = $ARGS{'age'} || 0;

None of the hash keys need quoting.
}

1;

package Employee;
use strict;
use warnings;

use Person;
our @ISA = qw( Person );

Better than these two lines is
use base qw/Person/;
as it happens at compile time.
sub new {
my $class = shift;

my $self = $class->SUPER::new( @_ );
$self->{'salary'} = 0;

This, again, is done by _init.
bless( $self, $class );

$self->_init( @_ );

These have already been done by Person::new (that's why you used two-arg
bless, remember :).
return $self;
}

sub _init {
my $self = shift;
my %ARGS = @_;

Here you want to call $self->SUPER::_init(@_), so that Person::_init
gets called. You probably also want to make the _init methods remove the
keys they know and return the rest:

$self->{salary} = (delete $ARGS{salary}) || 0;

return %ARGS;

and then in subclasses you can say

my %ARGS = $self->SUPER::_init(@_);

to let the superclass handle the keys it knows and return you the rest.
$self->{'salary'} = $ARGS{'salary'} || 0;
}

1;

Ben
 
T

Tore Aursand

You don't need to do this as you init them all in _init. You can just
say
my $self = bless {}, $class;

I see that as pretty irrelevant to my problem, and I _want_ to do it this
way. That way I can handle all the initialisation of the object inside a
special method, while the structure of the class in another.

Why? Well. Consider this _init() method;

sub _init {
my $self = shift;
my %ARGS = @_;

foreach ( keys %ARGS ) {
if ( exists $self->{$_} ) {
$self->{$_} = $ARGS{$_};
}
else {
warn "'$_' isn't a member of this class\n";
}
}
}

Easier to read the code, IMO; new() takes care of the class definition,
while _init() initialises it.
None of the hash keys need quoting.

I know, but that's not a problem. I helps me from going cross-eyed; my
editor highlights those strings so nice. :)
Better than these two lines is
use base qw/Person/;
as it happens at compile time.

Nice to know. What is the difference between these two methods? Are they
practically identical? Should one never need to use @ISA? (No, I haven't
read the 'perldoc base' yet, but I will do after writing this post). :)
These have already been done by Person::new (that's why you used two-arg
bless, remember :).

Aha. So I should never bless() an inherited class?

Just to sum up. Does this look better (forget about where I initialise
the data and how I quote, please)?

package Person;
use strict;
use warnings;

sub new {
my $class = shift;

my $self = {
'firstname' => '',
'lastname' => '',
'age' => 0,
};
bless( $self, $class );

$self->_init( @_ );

return $self;
}

sub _init {
my $self = shift;
}

1;

package Employee;
use strict;
use warnings;

use Person;
our @ISA = qw( Person );

sub new {
my $class = shift;

my $self = $class->SUPER::new( @_ );
$self->{'salary'} = 0;

return $self;
}

sub _init {
my $self = shift;

$self->SUPER::_init( @_ );
}

1;

I'm still using the @ISA, but this will - of course - be changed whenever
I find it suitable, as it didn't seem to do any difference in my example
above. :)


--
Tore Aursand <[email protected]>
"Omit needless words. Vigorous writing is concise. A sentence should
contain no unnecessary words, a paragraph no unnecessary sentences,
for the same reason that a drawing should have no unnecessary lines
and a machine no unnecessary parts." -- William Strunk Jr.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top