Почему вызов 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();
}