1. Skipping the middle man

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:

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!
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:
$me->Grandpa::hello(); __END__ % perl say_hello.pl How do you do, 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().

(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.

2. The SUPER gotcha

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:

package Me; # ... sub hello { my $self = shift; $self->Dad::hello(); print "I'm just a WILD AND CRAZY GUY!\n"; }
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->SUPER::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 like
package main; my $me = bless {}, 'Me'; $me->SUPER::hello;
perl will kick up a big fuss:
Can't locate object method "hello" via package "main" at hello.pl line + 27.
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:
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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.