Perl's OO interface is pretty flexible, and lets you do things easily that are awkward if not impossible in other languages1. One of these things can be labeled skip the middle man. Consider:
OK, now suppose that you liked Grandpa's hello better than Dad's. Well, you could override Me::hello by copying-and-pasting the code for Grandpa::hello, but Perl offers a simpler way; just skip the middle man:use strict; package Grandpa; sub hello { my $class = ref $_[0] || $_[0]; print "How do you do, from $class.\n"; } package Dad; our @ISA = 'Grandpa'; sub hello { my $class = ref $_[0] || $_[0]; print "Hiya from $class!\n"; } package Me; our @ISA = 'Dad'; package main; my $me = bless {}, 'Me'; # look Ma, no constructor! $me->hello; __END__ % perl say_hello.pl Hiya from Me!
Pretty cool, IMO. The "::" makes it look like a procedural interface call, but it is a bona fide OO method call, with an implicit instance (or package name) as first argument and all; a rather different animal from the similar-looking (and wrong2) Grandpa::hello().$me->Grandpa::hello(); __END__ % perl say_hello.pl How do you do, from Me.
(It wouldn't surprise me if this middle-man-skipping business is one of those things about Perl's take on OOP that make OO purists run for the hills, and maybe it is a result of those concerns that super.super.hello() makes Java have a cow. Dunno.)
Update: Indeed, as adrianh, merlyn, and brian_d_foy point out below, as cool as the flexibility to do this may appear (and I readily admit it does so to me), it is not a very good thing to do from the point of view of OO design.
You could also invoke $me->Dad::hello() but in this case, since Me does not override hello, the end result would be identical to that of invoking $me->hello(). However, if Me were overriding hello it may want to invoke Dad::hello at some point instead of its own hello, even (in fact most commonly) within the code for hello itself:
In general, however, it is good to avoid hard-coding class names (e.g. what if later on you decided that 'OldMan' was a more suitable name for the 'Dad' class?), so Perl offers a little help with the SUPER pseudo-class:package Me; # ... sub hello { my $self = shift; $self->Dad::hello(); print "I'm just a WILD AND CRAZY GUY!\n"; }
Now Me's hello invokes its parent's hello irrespective of the parent's name (it gets slightly more complicated if Me has more than one Daddy, aka multiple inheritance, but I won't go there; grep for "SUPER" in perlobj if you want the unsavory details). But the point I want to make is that despite the syntactic similarities between $me->SUPER::hello() and $me->Grandpa::hello(), SUPER and Grandpa are fundamentally different: Grandpa is a class, and SUPER is a pseudo-class. Whatever this "pseudo" means in deep ontological terms, for everyday program it's enough that it serve as a reminder that SUPER gets its meaning with respect to the current package, and not (as the arrow would suggest) with respect to the object that invokes it. In particular, contrary to Grandpa , whose meaning remains constant irrespective of the identity of the current package (as long as it has been loaded), the meaning of SUPER varies with the package. If you try something likepackage Me; #... sub hello { my $self = shift; $self->SUPER::hello(); print "I'm just a WILD AND CRAZY GUY!\n"; }
perl will kick up a big fuss:package main; my $me = bless {}, 'Me'; $me->SUPER::hello;
even though a call to $self->SUPER::hello was perfectly OK within Me's override of hello. This is the infamous SUPER gotcha. The moral of the story: if you want to use SUPER turn on the appropriate package if necessary:Can't locate object method "hello" via package "main" at hello.pl line + 27.
package Me; $me->SUPER::hello; package main;
When it comes to "skipping the middle man", though, Perl offers no help with avoiding hard-coding class names; you have no choice. I.e. $me->SUPER::SUPER::hello() will induce a bovine delivery in Perl too. Come to think of it, the fact that Perl provides no SUPER::SUPER is probably a clue that the designers of Perl don't think that skipping the middle man is such a hot idea. But, as is characteristic of Perl, they leave you a way to do it, if you really want to.
1Whether this is a bug or a feature, either in Perl or in those other languages (they know who they are) is another matter.
2In this particular case, at least, because the method is counting on having an instance or package name as its first argument. It is possible to write methods that can do double-duty as functions (e.g. consider the methods of the justly famed CGI module). Personally, I prefer simple interfaces over flexible interfaces, so I avoid such double-duty function/methods.
the lowliest monk
In reply to Skipping the middle man & the SUPER gotcha by tlm
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |