通常我会在课程__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;
}
Run Code Online (Sandbox Code Playgroud)
即使上面的代码适用于单个包,当一个对象使用该'Foo'角色自我反复,导致一个匿名类时会发生什么,然后第二个对象使用'Foo'(变成相同的anon类)然后'Bar'角色来祝福自己?当第二个对象将自己保存到不可变的第一个匿名类中时,它是否会正常工作,然后尝试将该角色应用于现在不可变的匿名类来创建一个新的匿名类?
通过阅读Moose :: Meta :: Class上的文档,看起来只有一个类可以是不可变的,而不是对象的实例.如果是这样,我是否应该忽略,make_immutable因为我正在改变我的课程?
你应该make_immutable像往常一样在课堂上做,而不是在你的课堂上担心BUILD.
在运行时将角色应用于实例时,它不会修改实例的类来应用角色(这将是混乱和可怕的并影响该类的所有其他实例); 它创建了一个新的匿名类,它继承自您的类并执行所请求的角色,然后将实例重新加入该类.由于原始类没有被修改,因此不存在是否开放/可变的问题.
实际上你可以$self->meta->make_immutable在角色应用程序之后做- 它会使新创建的匿名类不稳定 - 并且为了完整性你可能应该这样做.但它只会带来一个小的好处,因为大部分make_immutable功能是使构造函数更快,而新类的构造函数无论如何都不会运行.
如果要查看角色应用程序如何工作的详细信息,您应该查看Moose :: Meta :: Role :: Application :: ToInstance的来源.
| 归档时间: |
|
| 查看次数: |
2157 次 |
| 最近记录: |