2011-03-28 14 views
5

Normalmente finalizaría una clase en compilación a través del __PACKAGE__->meta->make_immutable al final de la clase. Sin embargo, ¿cuándo debería estar haciendo una clase inmutable que compone papeles en sí misma en tiempo de ejecución? ¿Debo hacerlo para obtener un mejor rendimiento o es esto incompatible con make_immutable? make_immutable parece acelerar la creación de instancias del objeto, pero ¿hace algo una vez que se crea una instancia del objeto?¿Cuándo debo hacer una clase Moose inmutable cuando estoy realmente usando -> meta?

Por ejemplo, algo a lo largo de las líneas de:

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

Incluso si el código anterior funciona para un solo paquete, lo que ocurre cuando un objeto reblesses sí con el papel 'Foo', lo que resulta en una clase anónima, a continuación, un segundo objeto se bendice con un 'Foo' (convirtiéndose en la misma clase anon) luego el rol 'Bar'? ¿Funcionará correctamente cuando el segundo objeto se bendiga en la primera clase anónima inmutable, y luego intente aplicar el rol a la clase anónima ahora inmutable para crear una nueva clase anónima?

Al leer los documentos en Moose::Meta::Class, parece que solo una clase puede ser inmutable, no instancias de objetos. Si es así, ¿debería estar ignorando make_immutable ya que estoy mutando mis clases?

Respuesta

7

Debería estar haciendo make_immutable como de costumbre en la parte inferior de su clase, y no preocuparse por ello en absoluto en su BUILD.

Cuando aplica un rol a una instancia en tiempo de ejecución, no modifica la clase de la instancia para aplicar el rol (que sería desordenado y horrible y afectaría a todas las demás instancias de esa clase); crea una nueva clase anónima que hereda de su clase y también realiza los roles solicitados, y luego replica la instancia en esa clase. Como la clase original no se está modificando, no hay problemas de si es abierta/mutable o no.

En realidad se puede qué $self->meta->make_immutable después de la aplicación de papel - que immutabilize la clase anónima de nueva creación - está completo y que probablemente debería. Pero solo dará un pequeño beneficio, ya que la mayor parte de lo que make_immutable hace es hacer que el constructor sea más rápido, y el constructor de la nueva clase no se ejecuta de todos modos.

Si desea ver los detalles de cómo funciona la aplicación de roles para las instancias, debe ver el origen de Moose::Meta::Role::Application::ToInstance.

+0

Y aun cuando establezca la nueva clase anónima como inmutable, la extensión sigue creando otra clase anónima que encapsula la primera clase inmutable de anon y la nueva función inmutable, por lo que la aplicación de roles a la clase anónima inmutable seguirá funcionando correctamente. ¡Lo tengo! – Oesor

Cuestiones relacionadas