jueves, 25 de septiembre de 2014

Perl: POO con Moose, Básico

Programación Orientada a Objetos en Perl con Moose

Para programar OO con Perl se puede usar la vieja escuela con perlobj (mediante un mecanismo conocido como bendición) o usar algo más moderno como uno de los sistemas de POO para Perl: Moose, Moo (Minimalist Object Orientation Moose compatible), Class::Accessor, Class::Tiny, Role::Tiny o Perl 6 OO (en el futuro). Aquí vamos a usar MooseMoose es un "postmodern object system for Perl 5" que hace más amigable la POO que la vieja escuela de perlobj.  En la vieja escuela era necesario crear el método new de las clases, en cambio con Moose no es necesario porque las clases heredan de Moose::Object quien ya implementa el new. O sea que prescindimos de la creación de constructores new.


Instalar Moose



Se debe por lo menos tener instalado Perl 5.8, pero es preferible 5.10 o 5.12. Moose se instala fácilmente con CPAN:

cpan Moose
#o se puede usar: sudo perl -MCPAN -e 'install Moose'
#o también: sudo apt-get install libmoose-perl

Ejemplos de Clases Moose:


1) Una Clase con Atributo String


#File: NameStr.pm
package NameStr;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'name' => (
                is         => 'rw', #Lectura-Escritura. También se puede usar 'ro' = read-only
  isa        => 'Str', #Tipo String (es obligatorio el valor string)
    );

    sub myNameIs
    {
        my $self = shift;
        my $myname = $self->name();
        print "My name: $myname \n";
    }


no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1; # Don't forget "1;" at end to return a true value from the file.
=pod
Nota 1: el  "isa  => 'Str'" hace que sea obligatorio que cuando se setea el valor el mismo sea string. Si se quiere que acepte un Undef lo que se debe poner es "isa => 'Maybe[Str]'".
Nota 2: Poner make_immutable junto con autoclean es una buena práctica Moose.
=cut

#...........................................................
#File: script_NameStr.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use NameStr; #Nuestra clase

my $instancia = NameStr->new();
$instancia->name('Daro');
$instancia->myNameIs();
#......................................................End

2) Una Clase con Atributo String y getter-setter

#Se puede usar getter and setter estilo Java

#File: NameStr.pm
package NameStr;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'name' => (
                is         => 'rw', #Lectura-Escritura
  isa        => 'Str', #Tipo String
                reader => 'getName', #getter
                writer => 'setName', #setter
    );

    sub myNameIs
    {
        my $self = shift;
        my $myname = $self->getName(); #getter
        print "My name: $myname \n";
    }


no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1;

#...........................................................
#File: script_NameStr.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use NameStr; #Nuestra clase

my $instancia = NameStr->new();
$instancia->setName('Daro'); #setter
$instancia->myNameIs();
#......................................................End

3) Una clase con atributo Integer


#File: AgeInt.pm
package AgeInt;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'age' => (
                is         => 'rw', #Lectura-Escritura
  isa        => 'Int', #Tipo Integer
                default =>  37            
    );


no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1;

#...........................................................
#File: script_AgeInt.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use AgeInt;  #Nuestra clase

my $instancia = AgeInt->new();
print $instancia->age() . "\n";
$instancia->age(19);
print $instancia->age() . "\n";
#......................................................End

4) Propiedades de atributos


#File: NameStrAtr.pm
package NameStrAtr;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'name' => (
                is         => 'rw', #Lectura/Escritura
  isa        => 'Str', #Tipo String
                reader => 'getName',
                writer => 'setName',
                required => 1, #Es requerido y no permite el valor 'undef'
                clearer   => 'clearName', #permite limpiar el valor, provoca que hasName devuelva false
                predicate => 'hasName', #devuelve true si tiene un valor
                lazy    => 1, #no se inicializa hasta que se llama al método lector
                default => '',
                init_arg => 'elNombre' #Nombre con el cual se referencia desde el constructor
    );

no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1;

#.............................................................................................................
#File: script_NameStrAtr.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use NameStrAtr; #Nuestra clase

my $instancia = NameStrAtr->new(elNombre=>'Daro'); #required
print "Nombre: " . $instancia->getName() . "\n"; #return 'Daro'
$instancia->setName('Daro Andres');
print "Nombre: " . $instancia->getName() . "\n"; #return 'Daro Andres'
print "Has value?: " . $instancia->hasName() . "\n"; #return 1 (true)
$instancia->clearName(); #Limpia el valor
print "Has value?: " . $instancia->hasName() . "\n"; #return (false)
#........................................................................................................End

5) Inicializadores de atributos con Builder   


#File: NameStrBuilt.pm
package NameStrBuilt;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'name' => (
                is         => 'rw', #Lectura/Escritura
  isa        => 'Str', #Tipo String
                reader => 'getName',
                writer => 'setName',
                builder   => 'buildName'

    );

    #Constructor inicializador del atributo name
    sub buildName {
        my $self = shift;
        $self->setName('Built Name (Nombre construido)'); #Inicializa
    }

no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1;

#.............................................................................................................
#File: script_NameStr.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use NameStrBuilt; #Nuestra clase

my $instancia = NameStrBuilt->new();
print "Nombre: " . $instancia->getName() . "\n"; #return 'Built Name (Nombre construido)'
#........................................................................................................End

6) Disparadores trigger en atributos

Un disparador es una función que es llamada cada vez que se cambia el atributo.

#File: NameStrTrigged .pm
package NameStrTrigged;

    use Moose;
    use strict; #Obliga a la programación segura y definición de variables
    use warnings; #Ayudará a encontrar errores de sintaxis
    use namespace::autoclean;

    has 'name' => (
                is         => 'rw', #Lectura/Escritura
  isa        => 'Str', #Tipo String
                reader => 'getName',
                writer => 'setName',
                trigger => \&triggerForSetName, #referencia a la función que se va a disparar cuando se setea el valor

    );

    #El trigger se dispara despues que se setea el atributo
    sub triggerForSetName {
        my ( $self, $name, $old_name ) = @_;
        if ($old_name){
            print "Trigger executed... new: ".$name." old: ".$old_name."\n";
        }
    }
 
no Moose;
__PACKAGE__->meta->make_immutable; #no voy a cambiar mi clase
1;

#.............................................................................................................
#File: script_NameStr.pl
#!/usr/bin/perl
use strict;
use warnings;
use Moose;
use NameStrTrigged; #Nuestra clase

my $instancia = NameStrTrigged->new(name=>'Nombre inicial');
print "Nombre: " . $instancia->getName() . "\n"; #return 'Built Name (Nombre construido)'
$instancia->setName('Segundo nombre');
print "Nombre: " . $instancia->getName() . "\n"; #return 'Built Name (Nombre construido)'
=pod
Se imprime en pantalla:
Nombre: Nombre inicial
Trigger executed... new: Segundo nombre old: Nombre inicial
Nombre: Segundo nombre
Presione una tecla para continuar . . .
=cut
#........................................................................................................End


Bueno, así vimos un resumen general del uso de clases con Moose.


Referencias:
http://en.wikibooks.org/wiki/Programming_with_Moose
https://dl.dropboxusercontent.com/u/45670449/Moose_Manual.pdf
http://modernperlbooks.com/books/modern_perl/chapter_07.html
https://www.perl.org/about/whitepapers/perl-object-oriented.html
https://metacpan.org/pod/Moose::Manual
http://perlmaven.com/object-oriented-perl-using-moose
https://metacpan.org/pod/Moo
http://perldoc.perl.org/perlootut.html#Role%3a%3aTiny

No hay comentarios:

Publicar un comentario