El problema es tradicional en Perl: como los objetos se guardan como diccionarios bautizados, no dejan de ser diccionarios, por lo que se puede acceder a su contenido como si fuera una variable global más.
Hay varias técnicas y módulos que solventan el problema.
* En
perltoot, en la sección Closures as Objects se describe cómo crear una función de clausura que haga referencia a un diccionario creado de forma local dentro del módulo, por lo que nadie podrá acceder a él de forma directa.
Using perl Syntax Highlighting
package Person
;
sub new {
my $class = shift;
my $self = {
NAME
=> undef,
AGE
=> undef,
PEERS
=> [],
};
my $closure = sub {
my $field = shift;
if (@_) { $self->{$field} = shift }
return $self->{$field};
};
bless($closure, $class);
return $closure;
}
sub name
{ &{ $_[0] }("NAME", @_[ 1
.. $#_ ] ) }
sub age
{ &{ $_[0] }("AGE", @_[ 1
.. $#_ ] ) }
sub peers
{ &{ $_[0] }("PEERS", @_[ 1
.. $#_ ] ) }
1;Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Así, los métodos de la clase son llamadas a la función de clausura (el elemento bautizado) que recibe como parámetro el nombre de la clave del diccionario local al que tiene que acceder. Ese diccionario es local solo al método (new) que lo usaba, así que no es conocido fuera.
La pega es que estamos hablando de una doble llamada de función, por lo que es lenta (o puede ser lenta para algunas aplicaciones).
En cambio, el uso es muy parecido:
Using perl Syntax Highlighting
use Person
;
$him = Person
->new();
$him->name("Jason");
$him->age(23
);
$him->peers( [ "Norbert", "Rhys", "Phineas" ] );
printf "%s is %d years old.\n", $him->name, $him->age;
print "His peers are: ", join(", ", @{$him->peers}), "\n";Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
* En
perltooc tienes un capítulo entero dedicado a la privacidad
* Está la técnica
inside-out (algo así como dar la vuelta al calcetín) (descrita en
Hash::Util::FieldHash). Consiste en lo siguiente: mientras que lo tradicional es bautizar un diccionario y colocar las propiedades del objeto como pares de claves y valores de ese diccionario, podemos crear un diccionario por cada propiedad, y cada clave de ese diccionario corresponde a un de los objetos de esa clase creados. Por definición, la dirección de referencia es única para cada objeto por lo que garantiza un lugar para cada campo, que es privado en la clase y único para cada objeto.
La idea es buena, salvo que necesita un método especial de destrucción de objetos.
Using perl Syntax Highlighting
{
package Name_id
;
use Hash
::Util::FieldHash qw(id
);
my (%first, %last);
sub init
{
my $obj = shift;
my ($first, $last) = @_;
# create an object if called as class method
$obj = bless \
my $o, $obj unless ref $obj;
$first{ id
$obj} = $first;
$last { id
$obj} = $last;
$obj;
}
sub first
{ $first{ id
shift()} }
sub last { $last { id
shift()} }
sub name
{
my $n = shift;
join ' ' => $n->first, $n->last;
}
sub DESTROY
{
my $id = id
shift;
delete $first{ $id};
delete $last { $id};
}
}Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
* Hay módulos que ayudan a esconder la información (ahora no me acuerdo de ninguno).
De todas formas, lo más moderno hoy en día es programar con
Moose.