Почему childClass вызывает свои функции parentClass, а также свои собственные?

Я начал осваивать наследование в Perl / Moose, но начинаю сталкиваться с некоторыми трудностями.

Например, порядок сборки унаследованных объектов кажется разумным, но наследование, похоже, работает не так, как я ожидал ...

Если мой baseClass вызывает BUILD, все подклассы будут вызывать свои BUILD, а также BUILD базового класса, но это не ограничивается функцией moosey BUILD.

Если я определяю функцию init () в базовом классе и вызываю ее из базового класса BUILD, подклассы init () вызываются вместо init () базового класса.

o_O

Для краткости предположим, что у нас есть следующие конструкции объектов:

BaseClass
    ::BUILD --> call init()
    ::init  --> do BaseStuff 

ChildClass extends BaseClass
    ::BUILD --> call init()
    ::init  --> do ChildStuff

Теперь создайте экземпляр childClass

my $child = ChildClass->new();

Результирующий порядок вызовов из new () для меня выглядит так, основываясь на моих выводах отладки

BaseClass->BUILD()
BaseClass->init() <--- this calls ChildClass::init
ChildClass->BUILD()
ChildClass->init() <--- this calls ChildClass::init too!

Я понимаю, что они оба называют BUILD a la Moose. Отлично. Думаю, я неправильно понимаю, почему baseClass в этом случае не вызывает свой собственный baseClass :: init или, альтернативно, почему childClass не просто вызывает свой собственный childClass :: BUILD.

Нужно ли мне специально «переопределять» эти функции с помощью модификатора функции Moose «переопределить»?

Тогда, если я добавлю BUILDARGS в микс, это станет еще интереснее, потому что вопрос в том, кто получает аргументы, передаваемые в new (), и что, если у baseClass есть связанные с ним роли?

BaseClass (has role CanSee and has seesWith() attribute)
BaseClass (has role NameTag and has name() attribute)
ChildClass (has role FavoriteColor and has color() attribute)

my $child = ChildClass->new( name => 'Jane', seesWith => 'eyes', color => 'red');

тогда

ChildClass
        ::BUILDARGS --> 
             ($orig,$class,$args) = @_;
             return $class->$orig(@_);

Какой $ class в этом случае ??

Не говорите мне, что я должен переопределить BUILDARGS ... лол


person qodeninja    schedule 21.10.2011    source источник


Ответы (1)


Я предполагаю, что у вас есть функция BUILD в каждом классе, немного похожая на

sub BUILD {
    my $self = shift;
    ...
    $self->init();
    ...
}

Moose обрабатывает BUILD иначе, чем Perl обычно обрабатывает вызовы методов. Когда вы вызываете init в своих методах BUILD, Perl будет использовать свое обычное разрешение метода и найдет дочерний метод init, поскольку он маскирует родительский метод init. Затем дочерний метод может вызывать родителей с $self->SUPER::init(), модификатором 'override' Moose, а super() - это просто измененный способ использования SUPER::.

Если вы вызываете init только в методе BUILD родительского класса, вы можете использовать любой из стандартных модификаторов метода Moose, например, «до», «после», «вокруг» или «переопределить», чтобы контролировать, когда init дочернего класса вызывается относительно родительский init.

Если, с другой стороны, вы хотите, чтобы инициализация каждого класса вызывалась при запуске сборки этого класса, вы можете специально попросить Perl пропустить поиск стандартного метода и использовать метод указанного класса:

package ParentClass;

sub BUILD {
    my $self = shift;
    ...
    $self->ParentClass::init();
    ...
}

package ChildClass;

sub BUILD {
    my $self = shift;
    ...
    $self->ChildClass::init();
    ...
}
person Ven'Tatsu    schedule 21.10.2011