Почему вызов Perl SUPER не использует метод стрелок?

Я заметил, что когда вы вызываете методы суперкласса, вам нужно сделать что-то вроде этого:

my $self = $class->SUPER::new();

Почему это не так:

my $self = $class->SUPER->new();

Ответы

Ответ 1

Я подозреваю, что $class->SUPER->new() обычно будет таким же, как $class->SUPER()->new(). Но нет функции $class->SUPER(), и ее неясно, что бы это получилось.

С другой стороны, $class->Foo::Bar всегда был правильным способом вызова метода напрямую по имени, поэтому создание специальной подобной пакету вещи - SUPER - лучше подходит. (Я подозреваю, что вы действительно могли бы реализовать SUPER как пакет, и, возможно, это исторически было, я не знаю)

PS: Посмотрите на пакет mro и $self->next::method. Кроме того, взгляните на Moose, если вы собираетесь сделать серьезную работу OO в Perl.

Ответ 2

Вызов метода имеет несколько форм:

Метод вызовов, возможно, унаследован:

->method()

Явно вызывает метод Sub:: Package, будь то в дереве наследования или нет:

->Package::method()

Явно вызывает связанный суб, независимо от того, что в дереве наследования:

->$coderef()

Вызывает метод, который был бы вызван __PACKAGE__->method(), если в __PACKAGE__ (N.B) не было подпорогового метода (класс или объект слева от -> не имеет значения):

->SUPER::method()

Любое из перечисленных выше, в зависимости от содержимого $method:

->$method()

(Законно даже при use strict;.)

В то время как первая форма является наиболее распространенной, стоит узнать о других и о том, как они работают.

Ответ 3

Короче говоря, SUPER не является методом. Это виртуальный пакет. Это описано в perlobj в разделе "Invoice".

Обратите внимание, однако, что SUPER основывается на текущем пакете, а не на пакете экземпляра, с которым вы его использовали.

Ответ 4

Чтобы добавить к тому, что сказал derobert:

Вы вызываете "новое" в пространстве имен "SUPER", но передаете ему объект (или строку), "$ class".

Вам не нужно использовать SUPER, так как вы можете указать полное имя родителя (полезно в случае наследования алмазов):

sub init {
   my $self = shift;
   $self->ParentClass1::init();
   $self->ParentClass2::init();
}