кваканье из метода сборки Moose

#perl #moose #carp

#perl #moose #карп

Вопрос:

Я хочу, чтобы мой класс взорвался, если BUILD метод завершится неудачей. Однако, если я использую croak для обработки ошибки, сообщение об ошибке поступает из Class/MOP/Method.pm , а не из кода вызывающего. (То есть вызывающий, который создает экземпляр объекта.) IOW, croak недостаточно лает в дереве вызовов.

Вот:

 package Test;

use Moose;
use Carp 'croak';

sub BUILD {
    croak 'u r dum';
}

1;
  

Создание экземпляра Test приводит к:

 u r dum at /home/friedo/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/Class/MOP/Method.pm line 125
  

Carp.pm предполагается, что он обращает внимание на переменную пакета, вызываемую @CARP_NOT , чтобы узнать, каких пакетов следует избегать, но, похоже, он обращает внимание только на один элемент в списке. Например, если я добавлю это в свой Test.pm :

 our @CARP_NOT = ( 'Class::MOP::Method' );
  

Тогда результат:

 u r dum at /home/friedo/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/Moose/Object.pm line 59
  

Так что я должен просто добавить это в массив, верно?

 our @CARP_NOT = ( 'Class::MOP::Method', 'Moose::Object'  );
  

Тогда результат по-прежнему:

 u r dum at /home/friedo/perl5/lib/perl5/x86_64-linux-gnu-thread-multi/Moose/Object.pm line 59
  

Moose::Object кажется, не затронуто.

Я уже некоторое время бьюсь головой об это и, похоже, не могу понять, что это портит.

Спасибо.

Ответ №1:

make_immutable кажется, это исправлено. Конечно, я не знаю, что делать, если вам нужно, чтобы ваши классы были изменяемыми.

Без make_immutable , Test->new вызывает Moose::Object->new . Если вы посмотрите на confess результат, вы заметите:

 Вызывается Test::BUILD(...) ...
 Вызывается класс ::MOP::Метод::execute(...) ...
 Вызван Moose::Object::BUILDALL(...) ...
 Вызван Moose::Meta::Class::new_object(...) ...
 Moose::Object::new('Test') вызывается по адресу ./t.pl строка 17
 #!/usr/bin/env perl

package Test;

use Moose;
use namespace::autoclean;

use Carp 'croak';

sub BUILD {
    croak 'u r dum';
}

__PACKAGE__->meta->make_immutable;

package main;

my $t = Test->new;
  

Вывод:

[sinan@archardy tmp] $ ./t.pl
u r dum в конструкторе Test::new (определено в ./t.pl строка 14) строка 28

Из Moose :: Поваренная книга ::Основы::Recipe7:

Во-вторых, вы больше не можете вносить изменения через API metaclass, такие как добавление атрибутов. На практике это не будет проблемой, так как вам редко нужно делать это после первой загрузки класса.

Мы настоятельно рекомендуем вам сделать ваши классы неизменяемыми. Это делает ваш код намного быстрее с небольшими затратами времени на компиляцию. Это будет особенно заметно при создании многих объектов.

Комментарии:

1. Ах, я даже не подумал об этом. Я всегда делаю ->make_immutable это как запоздалую мысль после того, как заканчиваю уточнять класс.

2. @friedo, пообещав больше не изменять класс во время текущего запуска , Moose создает эффективный конструктор для вашего класса. Это не мешает вам вообще менять модуль.

3. Я знаю — я должен добавить его в свой шаблон пакета вместо того, чтобы пытаться не забыть добавить его, когда я закончу.

4. К сожалению, это не работает для модификатора before метода.