如果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
似乎未受影响。
我一直在反对这个问题一段时间,似乎无法弄清楚是什么弄乱了它。
感谢。
答案 0 :(得分:6)
make_immutable
似乎解决了这个问题。当然,如果你确实需要你的课程可变,我不知道该怎么办。
如果没有make_immutable
,Test->new
会调用Moose::Object->new
。如果您查看confess
输出,请注意:
Test::BUILD(...) called ... Class::MOP::Method::execute(...) called ... Moose::Object::BUILDALL(...) called ... Moose::Meta::Class::new_object(...) called ... Moose::Object::new('Test') called at ./t.pl line 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 at constructor Test::new (defined at ./t.pl line 14) line 28
来自Moose::Cookbook::Basics::Recipe7:
其次,您无法再通过元类API进行更改,例如添加属性。在实践中,这不会是一个问题,因为您在首次加载课程后很少需要这样做。
...
我们强烈建议您使您的类不可变。它使您的代码更快,编译时成本很低。在创建许多对象时,这一点尤其明显。