Call parent method indirectly

E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

To call a method in a class indirectly, you do:

$self->$method(@args);

To call a specific method in the parent class, you do:

$self->SUPER::foo(@args);

How do you delegate to a parent method indirectly? This:

$self->SUPER::$method(@args);

doesn't work -- it reports "Bad name after ::".

Is there a way to do this without eval? I am using AUTOLOAD to generate
simple accessor/mutator methods in my class (table-driven design), and want
to delegate unknown methods to the parent class (since many methods will be
inherited from the parent).

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwQA8GPeouIeTNHoEQIBIQCcCLPo8nnh8y9liZ5t/XomMzkTk90An2Bj
kfso0B0KoynkEUulLEh3JTKr
=CGuJ
-----END PGP SIGNATURE-----
 
M

Malte Ubl

Eric said:
How do you delegate to a parent method indirectly? This:

$self->SUPER::$method(@args);

my $super = "SUPER::$method";
$self->$super(@args)
doesn't work -- it reports "Bad name after ::".

Is there a way to do this without eval? I am using AUTOLOAD to generate
simple accessor/mutator methods in my class (table-driven design), and want
to delegate unknown methods to the parent class (since many methods will be
inherited from the parent).

Maybe you want to use delegation to delegate (as opposed to inheritance)?

bye
malte
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Malte Ubl said:
my $super = "SUPER::$method";
$self->$super(@args)

Interesting. I will try it.

Maybe you want to use delegation to delegate (as opposed to
inheritance)?

I'm sorry, I was using the word "delegate" loosely. :)

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwRbz2PeouIeTNHoEQJ9GQCeMjozWvXlPlDGEtwqKZ3rGuaLqjkAoOLZ
BbrFtXFYxHMIEt7ZMl1eFo1S
=64Vv
-----END PGP SIGNATURE-----
 
B

Bart Lateur

Steve said:
You can also do:

$self->can("SUPER::$method")->(@args);

You forgot to pass along the object itself.

$self->can("SUPER::$method")->($self, @args);


I was wondering if there wasn't another way, something like

$self->SUPER->can($method)

but I guess not... :)
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

You forgot to pass along the object itself.

$self->can("SUPER::$method")->($self, @args);

I had no idea that can() returned a function pointer. I thought it was
just a boolean (1 or '').

I should know by now that when Perl has the option of returning something
*useful* as a true value, it does! Thanks, Steve and Bart.

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwVq5WPeouIeTNHoEQK8owCg2QWpwfR5qSDTwNCt8FlM0TDSjfAAoI3B
Vv7y8R1WvlGgqC01osoFHij8
=BUwY
-----END PGP SIGNATURE-----
 
S

Steve Grazzini

Bart Lateur said:
You forgot to pass along the object itself.

$self->can("SUPER::$method")->($self, @args);

I was wondering if there wasn't another way, something like

$self->SUPER->can($method)

but I guess not... :)

Yeah -- the first silly thing I tried was

$self->SUPER::can($method)->

:)
 
B

Benjamin Goldberg

Malte said:
Not that many people would care, but this is not thread safe!

It's only thread-unsafe if you're using the very deprecated 5.005
threading model.
The return value of C<can> can change over time, and time passes
between: $self->can("SUPER::$method")
and:
->($self, @args);

Maybe, but AFAIK, the only way that could possibly occur between the two
operations, in either non-threaded perl, or in perl with ithreads, would
be if we altered something through a signal handler.

Futhermore, so what? If @ISA of a module changes, or some method gets
added... well, we end up calling what can() returned, which is
"outdated" by a few microseconds, instead of the new value. If we'd
called the method directly, instead of with the intervention of can(),
then we'd probably still have gotten the "wrong" subroutine.

A slightly bigger deal is that ->can() might not call UNIVERSAL::can,
but instead call some class's overriden version of it.
No biggie, if you are not messing with @ISA at runtime or put code
references in it:

push @ISA, sub { rand > 0.5 ? "Hello::World" : "Destroy::HD" }

I know that you can put coderefs into @ISA, but I've never heard of them
going into @INC.
 
B

Bart Lateur

Benjamin said:
I know that you can put coderefs into @ISA, but I've never heard of them
going into @INC.

Heh. For me it's the other way around. For you too, I suppose.
 

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,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top