• Publicidad

Objetos y acceso a atributos

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Objetos y acceso a atributos

Notapor kondenado » 2009-07-29 09:48 @450

Buenas,

¿Alguien sabe si existe alguna manera de evitar que se pueda acceder directamente a los métodos de una instancia?

Por Ejemplo:

test.pl
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. # Suponer que existe el módulo TEST
  2. # y que la instancia posee los métodos new(sin parámetros)
  3. # y GetName (Devuelve el nombre)
  4. use TEST;
  5. use strict;
  6.  
  7. my $t = new TEST;
  8. my $nom = $t->GetName;        
  9. print "His name is $nom\n";
  10.  
  11. # Hasta aquí todo bien, a excepción de esto:
  12. print "His name is $t->{NAME}";
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


¿Se puede evitar esto?
Desde ya, gracias.

¡Saludos!
Perl programming
Avatar de Usuario
kondenado
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2006-08-21 18:57 @831

Publicidad

Re: Objetos y acceso a atributos

Notapor salva » 2009-07-29 11:48 @533

Hace como cosa de un par de años estuvieron muy de moda los objetos "inside-out" que permiten precisamente eso, ocultar los atributos de un objeto que solo son accesibles en el paquete donde se declara la clase... pero al final cayeron en desuso porque se vio que en la mayoría de los casos lo único que hacían era complicar las cosas, y además fueron eclipsados por Moose (que no aporta esa funcionalidad que tu buscas, pero sí otras generalmente más útiles).

En cualquier caso échale un vistazo al modulo Class::InsideOut y seguro que buscando en Google también te salen unos cuantos enlaces interesantes que expliquen la idea en detalle.
Avatar de Usuario
salva
Perlero nuevo
Perlero nuevo
 
Mensajes: 200
Registrado: 2008-01-03 15:19 @680

Re: Objetos y acceso a atributos

Notapor explorer » 2009-07-29 13:12 @592

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.
Sintáxis: [ Descargar ] [ Ocultar ]
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:
Sintáxis: [ Descargar ] [ Ocultar ]
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.002 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.

Sintáxis: [ Descargar ] [ Ocultar ]
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.002 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.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Objetos y acceso a atributos

Notapor kondenado » 2009-07-31 04:58 @249

Muchas gracias por las respuestas.

Luego de estudiar las alternativas presentadas creo que optaré por implementar Class::InsideOut mientras me doy el tiempo de aprender Moose (aún no me acostumbro).

Aunque el método de bendecir subrutinas anónimas está bien interesante, no me puedo arriesgar a aumentar el uso de memoria por la doble llamada de función.

¡Saludos!
Perl programming
Avatar de Usuario
kondenado
Perlero nuevo
Perlero nuevo
 
Mensajes: 43
Registrado: 2006-08-21 18:57 @831


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado