通常,我会在编译时通过__PACKAGE__->meta->make_immutable在类的末尾结束一个类。但是,我应该在什么时候让一个在运行时将角色组合成自身的类成为不可变的?我是否应该这样做以获得更好的性能,或者这与make_immutable不兼容?make_immutable似乎可以加快对象的实例化速度,但一旦对象实例化,它会做什么吗?
例如,类似如下的内容:
BUILD {
my $self = shift;
use Module::Load;
### Use the arguments passed in to determine roles applicable to
### this instance of the object. Load and apply roles.
for my $role ($self->_determine_roles()) {
load $role;
$role->meta->apply($self);
}
### $self is now a Class::MOP::Class::__ANON__... anonymous class
### Should I then be saying I'm done mutating it with something like this?
### can make_immutable even be run on an object instance and not a package?
$self->meta->make_immutable;
}即使上面的代码适用于单个包,当一个对象使用'Foo'角色重新定义自己,产生一个匿名类,然后第二个对象使用'Foo' (成为相同的anon类)而不是'Bar'角色来保护自己时,会发生什么呢?当第二个对象将自己添加到不可变的第一个匿名类中,然后尝试将角色应用于现在不可变的匿名类以创建新的匿名类时,它是否会正常工作?
通过阅读Moose::Meta::Class上的文档,似乎只有一个类可以是不可变的,而不是对象的实例。如果是这样,我是否应该忽略make_immutable,因为我正在改变我的类?
发布于 2011-03-29 01:24:47
你应该像往常一样在你的类的底部做make_immutable,而不是在你的BUILD中担心它。
当您在运行时将角色应用于一个实例时,它不会修改该实例的类来应用该角色(这将是混乱和可怕的,并且会影响该类的所有其他实例);它会创建一个新的匿名类,该类继承自您的类并执行所请求的角色,然后将该实例重新绑定到该类中。由于原始类没有被修改,所以不存在它是否是开放/可变的问题。
实际上,您可以在角色应用程序之后执行$self->meta->make_immutable -它将使新创建的匿名类不可变-为了完整性,您可能应该这样做。但它只会带来很小的好处,因为make_immutable做的大多数事情都是为了让构造函数更快,而且新类的构造函数无论如何都不会运行。
如果您想了解角色应用到实例的工作原理的详细信息,您可以查看Moose::Meta::Role::Application::ToInstance的源代码。
https://stackoverflow.com/questions/5462534
复制相似问题