2011-03-28 47 views
5

通常我会在课程结束时通过__PACKAGE__->meta->make_immutable进行汇编。然而,我应该在什么时候让一个不可变的类在运行时将其组合到自身中?我是否应该这样做才能获得更好的表现,或者这与make_immutable不兼容? make_immutable似乎加快了对象的实例化,但它是否在对象实例化后执行任何操作?当我真正使用 - > meta时,何时应该使Moose类不可变?

例如,沿着线的东西:

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; 
} 

即使上面的代码适用于单一封装中,当一个对象reblesses本身与'Foo'作用,产生一个匿名类会发生什么,然后第二个对象用'Foo'祝福自己(成为那个相同的匿名类)然后'Bar'的作用?当第二个对象自己加入到不可变的第一个匿名类中,然后尝试将该角色应用于现在不可变的匿名类来创建一个新的匿名类时,它会正常工作吗?

从阅读有关Moose::Meta::Class的文档,看起来只有一个类可以是不可变的,而不是对象的实例。如果是这样,我应该忽略make_immutable,因为我正在改变我的课程吗?

回答

7

你应该像平常一样在课堂上做make_immutable,而不用担心你的BUILD

当您在运行时将角色应用于实例时,它不会修改实例的类以应用该角色(这将是混乱和可怕的并会影响该类的所有其他实例);它会创建一个新的匿名类,该类从您的类继承并执行请求的角色,然后将该实例重新分配给该类。由于原始类没有被修改,所以不存在是否是开放/可变的问题。

你实际上可以$self->meta->make_immutable角色应用程序后 - 它会使新创建的匿名类免疫 - 为了完整性,你可能应该。但它只会带来一点好处,因为make_immutable所做的大部分工作是使构造函数更快,而新类的构造函数不会运行。

如果您想查看应用程序对实例的角色工作方式的详细信息,您应该查看Moose::Meta::Role::Application::ToInstance的来源。

+0

即使当我将新的匿名类设置为不可变时,它仍然创建另一个匿名类,它封装了第一个不可变匿名类和新不可变角色,因此将角色应用于不可变匿名类仍然可以正常工作。得到它了! – Oesor 2011-03-28 18:04:27

相关问题