ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



13.10. Accessing Overridden Methods

Problem

Your constructor method overrides the constructor of a parent class. You want your constructor to call the parent class's constructor.

Solution

Learn about the special class, SUPER.

sub meth { 
    my $self = shift;
    $self->SUPER::meth();
}

Discussion

In languages like C++ where constructors don't actually allocate memory but just initialize the object, all base class constructors are automatically called for you. In languages like Java and Perl, you have to call them yourself.

To call a method in a particular class, the notation $self->SUPER::meth() is used. This is an extension of the regular notation to start looking in a particular base class. It is only valid from within an overridden method. Here's a comparison of styles:

$self->meth();                # Call wherever first meth is found
$self->Where::meth();         # Start looking in package "Where"
$self->SUPER::meth();         # Call overridden version

Simple users of the class should probably limit themselves to the first one. The second is possible, but not suggested. The last must only be called from within the overridden method.

An overriding constructor should call its SUPER's constructor to allocate and bless the object, limiting itself to instantiating any data fields needed. It makes sense here to separate the object allocation code from the object initialization code. We'll name it with a leading underscore, a convention indicating a nominally private method. Think of it as a "Do Not Disturb" sign.

sub new {
    my $classname  = shift;         # What class are we constructing?
    my $self       = $classname->SUPER::new(@_);
    $self->_init(@_);
    return $self;                   # And give it back
} 

sub _init {
    my $self = shift;
    $self->{START}   = time();   # init data fields
    $self->{AGE}     = 0;
    $self->{EXTRA}   = { @_ };   # anything extra
}

Both SUPER::new and _init have been called with any remaining arguments. That way the user might pass other field initializers in, as in:

$obj = Widget->new( haircolor => red, freckles => 121 );

Whether you store these user parameters in their own extra hash or not is up to you.

Note that SUPER only works on the first overridden method. If your @ISA array has several classes, it only gets the first one. A manual traversal of @ISA is possible, but probably not worth the hassle.

my $self = bless {}, $class;
for my $class (@ISA) {
    my $meth = $class . "::_init";
    $self->$meth(@_) if $class->can("_init");
} 

This fragile code assumes that all superclasses initialize their objects with _init instead of initializing in the constructor. It also assumes that a hash reference is used for the underlying object.

See Also

The discussion on the SUPER class in perltoot (1) and perlobj (1), and in the section on "Method Invocation" in Chapter 5 of Programming Perl


Previous: 13.9. Writing an Inheritable ClassPerl CookbookNext: 13.11. Generating Attribute Methods Using AUTOLOAD
13.9. Writing an Inheritable ClassBook Index13.11. Generating Attribute Methods Using AUTOLOAD