perl - ¿Cómo puedo crear variables internas(privadas) de objetos de Moose(atributos)?
(5)
Me gustaría que algunos atributos (quizás este es el término incorrecto en este contexto) sean privados, es decir, solo internos para el uso del objeto, no se pueden leer ni escribir desde el exterior.
Por ejemplo, piense en alguna variable interna que cuente el número de veces que se llamó a un conjunto de métodos.
¿Dónde y cómo debo definir tal variable?
Alan W. Smith proporcionó una variable de clase privada con una variable léxica, pero todos los objetos de la clase la comparten. Intente agregar un nuevo objeto al final de la secuencia de comandos de ejemplo:
my $c1 = CountingObject->new();
printf( "%s/n", $c1->get_count() );
# also shows a count of 10, same as $co
Uso de MooseX: la privacidad es una buena respuesta, aunque si no puedes, puedes tomar prestado un truco del campamento de objetos de adentro hacia afuera:
package CountingObject;
use Moose;
my %cntr;
sub BUILD { my $self = shift; $cntr{$self} = 0 }
sub add_one { my $self = shift; $cntr{$self}++; }
sub get_count { my $self = shift; return $cntr{$self}; }
1;
Con eso, el contador de cada objeto se almacena como una entrada en un hash léxico. Lo anterior se puede implementar un poco más tersamente así:
package CountingObject;
use Moose;
my %cntr;
sub add_one { $cntr{$_[0]}++ }
sub get_count { return $cntr{$_[0]}||0 }
1;
Creo que quieres MooseX::Privacy .
El perldoc le dice todo lo que necesita, agrega un nuevo rasgo a sus atributos que le permite declararlos como privados o protegidos:
has config => (
is => ''rw'',
isa => ''Some::Config'',
traits => [qw/Private/],
);
No he podido encontrar una manera de hacer que los atributos de Moose sean completamente privados. Cada vez que uso has ''name'' => (...);
para crear un atributo, siempre está expuesto a la lectura como mínimo. Para los artículos que quiero que sean realmente privados, estoy usando variables "mi" estándar dentro del paquete Moose. Para un ejemplo rápido, tome el siguiente módulo "CountingObject.pm".
package CountingObject;
use Moose;
my $cntr = 0;
sub add_one { $cntr++; }
sub get_count { return $cntr; }
1;
Los scripts que usan ese módulo no tienen acceso directo a la variable $ cntr. Deben usar los métodos "add_one" y "get_count" que actúan como una interfaz para el mundo exterior. Por ejemplo:
#!/usr/bin/perl
### Call and create
use CountingObject;
my $co = CountingObject->new();
### This works: prints 0
printf( "%s/n", $co->get_count() );
### This works to update $cntr through the method
for (1..10) { $co->add_one(); }
### This works: prints 10
printf( "%s/n", $co->get_count() );
### Direct access won''t work. These would fail:
# say $cntr;
# say $co->cntr;
Soy nuevo en Moose, pero por lo que puedo decir, este enfoque proporciona variables completamente privadas.
Puedes probar algo como esto:
has ''call_counter'' => (
is => ''ro'',
writer => ''_set_call_counter'',
);
is => ''ro''
hace que el atributo sea de solo lectura . Alce genera un captador. Sus métodos utilizarán el getter para incrementar el valor, de esta manera:
sub called {
my $self = shift;
$self->_set_call_counter( $self->call_counter + 1 );
...
}
writer => ''_set_call_counter''
genera un setter llamado _set_call_counter
. Moose no soporta verdaderos atributos privados . El código externo puede, técnicamente, llamar a _set_call_counter
. Sin embargo, por convención, las aplicaciones no llaman a los métodos que comienzan con un guión bajo.
Moose::Manual::Attributes
muestra la siguiente forma de crear atributos privados:
has ''_genetic_code'' => (
is => ''ro'',
lazy => 1,
builder => ''_build_genetic_code'',
init_arg => undef,
);
La configuración de init_arg
significa que este atributo no se puede establecer en el constructor. Haz que sea un rw
o agrega un writer
si necesitas actualizarlo.
/ I3az /