New to Perl, OOP inheritance

P

Peter Michaux

Hi,

I'm new to Perl (from C, JavaScript, Ruby) and going through the Camel
book.

Below is my an example of trying to write Ruby/Java style class-based
inheritance in Perl. (In JavaScript, Ruby and Java I would write like
this <URL: http://peter.michaux.ca/article/1>) The first eight lines
of each new subroutine below seems quite clunky. I'm trying to make it
so the new can be called either to instantiate a new object or be
called as super from a child class's constructor. I only want to name
the parent class once in the @ISA and use SUPER everywhere else so I
can change the inheritance chain easily.

package Person;

sub new {
my $invocant = shift;
my $this;
if (ref($invocant)) {
$this = $invocant;
} else {
$this = {};
bless($this, $invocant);
}
my ($name) = @_;
$this->{name} = $name;
return $this;
}

sub toString {
$this = shift;
return $this->{name};
}

# ---------------------------------------------

package Employee;
our @ISA = ('Person');

sub new {
my $invocant = shift;
my $this;
if (ref($invocant)) {
$this = $invocant;
} else {
$this = {};
bless($this, $invocant);
}
my ($name, $id) = @_;

$this->SUPER::new($name);
$this->{id} = $id;
return $this;
}

sub toString {
my $this = shift;
return $this->SUPER::toString() . ': ' . $this->{id};
}

# ---------------------------------------------

$ted = Employee->new('Ted', 10);
print ($ted->toString(), "\n");


Any suggestions to clean up the clunky parts of the new subroutines? I
expect that some will say "this is not how you do OOP Inheritance in
Perl." Other options?

Thank you,
Peter
http://peter.michaux.ca
http://forkjavascript.org
 
A

anno4000

Peter Michaux said:
Hi,

I'm new to Perl (from C, JavaScript, Ruby) and going through the Camel
book.

Below is my an example of trying to write Ruby/Java style class-based
inheritance in Perl. (In JavaScript, Ruby and Java I would write like
this <URL: http://peter.michaux.ca/article/1>) The first eight lines
of each new subroutine below seems quite clunky. I'm trying to make it
so the new can be called either to instantiate a new object or be
called as super from a child class's constructor. I only want to name
the parent class once in the @ISA and use SUPER everywhere else so I
can change the inheritance chain easily.

So if ->new is called as an object method it (re-)initializes the
object. That's a reasonable approach, though it might be clearer
to have separate methods (object method ->init, class method ->new)
for that.
package Person;

sub new {
my $invocant = shift;
my $this;
if (ref($invocant)) {
$this = $invocant;
} else {
$this = {};
bless($this, $invocant);
}
my ($name) = @_;
$this->{name} = $name;
return $this;
}

sub toString {
$this = shift;
return $this->{name};
}

# ---------------------------------------------

package Employee;
our @ISA = ('Person');

sub new {
my $invocant = shift;
my $this;
if (ref($invocant)) {
$this = $invocant;
} else {
$this = {};
bless($this, $invocant);
}
my ($name, $id) = @_;

$this->SUPER::new($name);
$this->{id} = $id;
return $this;
}

sub toString {
my $this = shift;
return $this->SUPER::toString() . ': ' . $this->{id};
}

# ---------------------------------------------

$ted = Employee->new('Ted', 10);
print ($ted->toString(), "\n");


Any suggestions to clean up the clunky parts of the new subroutines? I
expect that some will say "this is not how you do OOP Inheritance in
Perl." Other options?

You can pack most of the "clunky part" in one statement:

sub new {
my $invocant = shift;
my $this = ref( $invocant) ? $invocant : bless {}, $invocant;
my ($name) = @_;
# ...
}

Anno
 
P

Peter Michaux

So if ->new is called as an object method it (re-)initializes the
object. That's a reasonable approach, though it might be clearer
to have separate methods (object method ->init, class method ->new)
for that.














You can pack most of the "clunky part" in one statement:

sub new {
my $invocant = shift;
my $this = ref( $invocant) ? $invocant : bless {}, $invocant;
my ($name) = @_;
# ...
}

Anno


Thanks for the reply. Good to know I wasn't way out in left field.

Peter
 
A

anno4000

Peter Michaux said:
[...]
So if ->new is called as an object method it (re-)initializes the
object. That's a reasonable approach, though it might be clearer
to have separate methods (object method ->init, class method ->new)
for that.
[...]
You can pack most of the "clunky part" in one statement:

sub new {
my $invocant = shift;
my $this = ref( $invocant) ? $invocant : bless {}, $invocant;
my ($name) = @_;
# ...
}

Anno


Thanks for the reply. Good to know I wasn't way out in left field.

Let me take the occasion and add a few more general remarks.

It is a good thing for a class to have not only a creator but also
a separate initializer. This aspect has been sadly neglected by
the Perl OO community. If creation and initialization are coupled,
you're in trouble with multiple inheritance. You can create an
object only once, but you must (potentially) initialize it for
every class it inherits from. Perl classes traditionally come
with only a creator, neglecting that simple arithmetic.

Your approach to have ->new behave like an initializer if called
on an object is one way to provide separate initialization. The
semantics could be expressed as "set this object up according to
the arguments as if it were new", which is reasonable enough.

Unfortunately, a large strain of Perl classes has emerged whose
->new methods show an entirely different behavior when called as
an object method. The done thing is (was? it seems to be declining)
to derive a class from the object via the attractive idiom

my $class = ref( $invocant) || $invocant;

....and plough ahead creating a new object, no matter what. In
the rare situations where that behavior is useful, I find it
clearer to express it on the client level as

my $like_the_other = ref( $obj)->new( ...);

I don't remember ever wanting that except in some cross-class
overloading situations. The need for separate initialization
comes up regularly with multiple inheritance, so the behavior
you suggest is far more useful. It is perhaps no coincidence
that you spontaneously came up with it. It appears you are
familiar with OO in general, but not with the particular quirks
of Perl's OO culture.

Anno
 
P

Peter Michaux

Hi Anno,

On Feb 16, 5:18 pm, (e-mail address removed)-berlin.de wrote:

Unfortunately, a large strain of Perl classes has emerged whose
->new methods show an entirely different behavior when called as
an object method. The done thing is (was? it seems to be declining)
to derive a class from the object via the attractive idiom

my $class = ref( $invocant) || $invocant;

...and plough ahead creating a new object, no matter what.

I read this style in the Camel book at did a complete double take. I
haven't encountered a situation where I'd want to do that. Then again
I haven't had that possibility available before so haven't thought
about what efficiency it allows.
In
the rare situations where that behavior is useful, I find it
clearer to express it on the client level as

my $like_the_other = ref( $obj)->new( ...);

I think this is much nicer and makes the Perl OOP system more like
other OOP languages. Not that Perl should be written like other
languages but if developers like me are showing up into some Perl
scripts it will make more sense.
I don't remember ever wanting that except in some cross-class
overloading situations. The need for separate initialization
comes up regularly with multiple inheritance, so the behavior
you suggest is far more useful. It is perhaps no coincidence
that you spontaneously came up with it. It appears you are
familiar with OO in general, but not with the particular quirks
of Perl's OO culture.

I think I'm a little spoiled coming from Ruby which built on Perl's
successes. The Perl quirks I've read so far have been interesting :)

Thanks again,
Peter
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top