NOMBRE

perlootut - Manual de programación orientada a objetos en Perl

FECHA

Creado en febrero de 2011.

DESCRIPCIÓN

Este documento proporciona una introducción a la programación orientada a objetos en Perl. Comienza con una breve descripción de los conceptos relacionados con el diseño orientado a objetos. A continuación presenta varios sistemas diferentes de orientación a objetos, disponibles en CPAN, construidos sobre la base proporcionada por Perl.

El sistema de orientación a objetos predeterminado de Perl es minimalista; deja al usuario la mayor parte del trabajo. Este minimalismo tenía sentido en 1994, pero en los años que han transcurrido desde que se lanzó Perl 5.0 han surgido diversos patrones comunes en la orientación a objetos de Perl. Afortunadamente, la flexibilidad de Perl ha permitido que florezca un variado ecosistema de sistemas orientados a objetos en el lenguaje.

Si desea conocer el funcionamiento interno de la orientación a objetos en Perl, este documento explica los detalles esenciales.

Suponemos que ya conoce y comprende la sintaxis de Perl, los tipos de variables y las llamadas a subrutinas. De no ser así, lea primero perlintro. También debería leer los documentos perlsyn, perlop y perlsub.

FUNDAMENTOS DE LA ORIENTACIÓN A OBJETOS

La mayoría de los sistemas orientados a objetos comparten una serie de conceptos comunes. Probablemente ya conoce términos como "clase", "objeto", "método" y "atributo". La comprensión de estos conceptos hará más fácil la lectura y escritura de código orientado a objetos. Aunque ya esté familiarizado con estos conceptos, debería leer por encima esta sección, puesto que explica cada concepto en términos de la implementación de la orientación a objetos de Perl.

El sistema de orientación a objetos de Perl se basa en clases. La orientación a objetos basada en clases en bastante común. Se usa en Java, C++, C#, Python, Ruby y otros muchos lenguajes. Hay otros paradigmas de orientación a objetos. JavaScript es el lenguaje más popular que usa un paradigma diferente; el sistema de orientación a objetos de JavaScript se basa en prototipos.

Objeto

Un objeto es una estructura de datos que empaqueta datos y subrutinas que operan sobre los datos. Los datos de un objeto se denominan atributos y las subrutinas se denominan métodos. Un objeto puede verse como un nombre (una persona, un servicio web, un PC...).

Representa una única cosa. Por ejemplo, un objeto podría representar un archivo. Los atributos de un objeto que representa un archivo podrían incluir su ruta, el contenido y la hora de la última modificación. Si se crea un objeto para representar el archivo /etc/hostname en un equipo llamado "foo.ejemplo.com", la ruta del objeto sería "/etc/hostname", su contenido "foo\n" y la hora de la última modificación podría ser de 1304974868 segundos desde el principio del tiempo Unix.

Los métodos asociados a un archivo podrían incluir renombrar() y escribir().

En Perl la mayoría de los objetos son hashes, pero los sistemas de orientación a objetos recomendados evitan tener que preocuparse de estos detalles. En la práctica es mejor considerar opaca la estructura interna de los objetos.

Clase

Una clase define el comportamiento de una categoría de objetos. Es un nombre para una categoría (como "Archivo"); también define el comportamiento de los objetos de esa categoría.

Todos los objetos pertenecen a una clase específica. Por ejemplo, nuestro objeto /etc/hostname pertenece a la clase Archivo. Para construir un objeto específico, se comienza con la clase asociada y se construye (o se crea una instancia de) un objeto. Un objeto específico se suele llamar una instancia de la clase.

En Perl, cualquier paquete puede ser una clase. La diferencia entre un paquete que es una clase y uno que no lo es radica únicamente en cómo se utiliza. A continuación se muestra la "declaración de la clase" Archivo:

package Archivo;

En Perl no hay una palabra reservada especial para construir un objeto. Sin embargo, la mayoría de los módulos orientados a objetos disponibles en CPAN usan el método new() para construir un objeto nuevo:

my $nombre_host = Archivo->new(
    ruta         => '/etc/hostname',
    contenido    => "foo\n",
    hora_ult_mod => 1304974868,
);

(No se preocupe por el operador ->; se explicará más adelante).

Bendición

Como se ha indicado anteriormente, la mayoría de los objetos de Perl son hashes, pero un objeto puede ser una instancia de cualquier tipo de datos de Perl (escalar, array, etc). La conversión de una estructura de datos normal en un objeto se realiza mediante la bendición de la misma con la función bless de Perl.

Aunque recomendamos no construir objetos partiendo de cero, debe conocer el concepto de bendición. Una estructura de datos bendecida (también conocida como "referente") es un objeto. A veces se dice que un objeto ha sido "bendecido en una clase".

Una vez que un referente ha sido bendecido, la función blessed del módulo Scalar::Util indicará el nombre de la clase asociada. Esta subrutina devuelve la clase del objeto cuando se le pasa un objeto como argumento, y falso en cualquier otro caso.

use Scalar::Util 'blessed';

print blessed($hash);         # undef
print blessed($nombre_host);  # Archivo

Constructor

Un constructor crea un nuevo objeto. En Perl, el constructor de una clase es un método más; otros lenguajes de programación tienen una sintaxis especial para ellos. La mayoría de las clases Perl usan new como nombre del constructor:

my $archivo = Archivo->new(...);

Métodos

Ya se ha indicado que un método es una subrutina que opera sobre un objeto. Se puede considerar que los métodos de un objeto son las operaciones que un objeto puede hacer. Si un objeto es un sustantivo, entonces los métodos son sus verbos (guardar, imprimir, abrir).

En Perl, los métodos no son más que subrutinas que pertenecen al paquete de una clase. Los métodos siempre se programan de forma que el primer argumento recibido sea el objeto:

sub imprimir_info {
    my $self = shift;

    print "Ruta del archivo: ", $self->ruta, "\n";
}

$archivo->imprimir_info;
# Ruta del archivo: /etc/hostname

Lo que hace especiales a los métodos es la forma de llamarlos. El operador flecha (->) le indica a Perl que se está llamando a un método.

Cuando se hace la llamada a un método, Perl pasa el autor de la llamada como primer argumento. Autor de la llamada es un nombre elaborado que simplemente quiere decir lo que está a la izquierda de la flecha. El autor de la llamada puede ser un nombre de clase o un objeto. También pueden pasarse argumentos adicionales al método:

sub imprimir_info {
    my $self    = shift;
    my $prefijo = shift // "Ruta del archivo: ";

    print $prefijo, ", ", $self->ruta, "\n";
}

$file->imprimir_info("El archivo se encuentra en ");
# El archivo se encuentra en /etc/hostname

Atributos

Cada clase puede definir sus atributos. Cuando se crea una instancia de un objeto, se asignan valores a sus atributos. Por ejemplo, cada objeto de la clase Archivo tiene su propia ruta. Los atributos también se suelen llamar propiedades.

Perl no dispone de una sintaxis especial para los atributos. Internamente, los atributos se suelen almacenar como claves del hash subyacente del objeto, pero no debe preocuparse de estos detalles.

Le recomendamos que solo acceda a los atributos a través de los métodos de acceso. Estos son métodos que permiten obtener o establecer el valor de cada atributo. Ya vimos esto antes en el ejemplo imprimir_info(), que llama a $self->ruta.

También puede ver los términos getter y setter. Son dos tipos de métodos de acceso. Un método getter obtiene el valor del atributo, mientras que un método setter lo establece. Un método setter también se puede llamar mutator (modificador).

Los atributos se suelen definir como de solo lectura o de lectura y escritura. Los atributos de solo lectura solo se pueden asignar al crear el objeto; los de lectura y escritura pueden modificarse en cualquier momento.

El valor de un atributo puede ser a su vez otro objeto. Por ejemplo, en lugar de devolver la hora de última modificación como un número, la clase Archivo podría devolver un objeto de clase DateTime que representa este valor.

Es posible tener una clase donde no pueda modificarse ningún atributo. No todas las clases tienen atributos y métodos.

Polimorfismo

El polimorfismo es una forma elegante de decir que los objetos de dos clases distintas comparten una API. Por ejemplo, podríamos tener las clases Archivo y PaginaWeb, ambas con un método imprimir_contenido(). Este método puede producir salidas diferentes para cada clase, pero la interfaz es común.

Las dos clases pueden ser distintas por diferentes razones, pero en lo que se refiere el método imprimir_contenido() se comportan de la misma forma. Esto significa que podemos intentar llamar al método imprimir_contenido() desde un objeto de cualquiera de estas clases sin saber a qué clase pertenece el objeto.

El polimorfismo es uno de los conceptos clave del diseño orientado a objetos.

Herencia

La herencia permite crear una versión especializada de una clase existente. Mediante herencia, las nuevas clases pueden reutilizar los métodos y atributos de otra clase.

Por ejemplo, podríamos crear una clase Archivo::MP3 que herede de Archivo. Un objeto de la clase Archivo::MP3 es un (is-a) tipo de objeto más específico que un objeto de la clase Archivo. Todos los archivos mp3 son archivos, pero no todos los archivos son archivos mp3.

A menudo se alude a las relaciones de herencia como relaciones primario-derivado o superclase/subclase. Algunas veces se dice que la clase derivada tiene una relación de tipo "es un" (is-a en inglés) con su clase primaria.

Archivo es una superclase de Archivo::MP3 y Archivo::MP3 es una subclase de Archivo.

package Archivo::MP3;

use parent 'Archivo';

El módulo parent es una de las muchas formas disponibles en Perl para definir relaciones de herencia.

Perl permite la herencia múltiple: una clase puede heredar de múltiples clases primarias. Aunque esto es posible, se recomienda rotundamente no hacerlo. En general, pueden usarse roles para conseguir todo lo ofrecido por la herencia múltiple, pero de forma mucho más limpia.

No hay nada malo en definir múltiples subclases de una clase. Esto es habitual y seguro. Por ejemplo, podríamos definir las clases Archivo::MP3::VelBitsFija y Archivo::MP3::VelBitsVariable para distinguir entre diferentes tipos de archivos mp3.

Sobrescritura de métodos y resolución de métodos

La herencia permite que dos clases compartan código. De manera predeterminada, cada método de la clase primaria también estará disponible en la clase derivada. La clase derivada puede sobrescribir un método de la clase primaria para ofrecer su propia implementación. Por ejemplo, si tenemos un objeto de la clase Archivo::MP3, hereda el método imprimir_info() de la clase Archivo:

my $minero = Archivo::MP3->new(
    ruta          => 'mp3/Soy-minero.mp3',
    contenido     => $datos_mp3,
    hora_ult_mod => 1304974868,
    titulo        => 'Soy minero',
);

$minero->imprimir_info;
# Ruta del archivo: mp3/Soy-minero.mp3

Si deseamos incluir el título del archivo mp3 en el saludo podemos sobrescribir el método:

package Archivo::MP3;

use parent 'Archivo';

sub imprimir_info {
    my $self = shift;

    print "Ruta del archivo: ", $self->ruta, "\n";
    print "Título: ", $self->titulo, "\n";
}

$minero->imprimir_info;
# Ruta del archivo: mp3/Soy-minero.mp3
# Título: Soy minero

El proceso de determinar qué método debe usarse se denomina resolución de métodos. Perl busca en primer lugar en la clase del objeto (Archivo::MP3 en este caso). Si la clase define el método, se llama a la versión del método en la misma. Si no, Perl busca en cada clase primaria por orden. La única clase primaria de Archivo::MP3 es Archivo. Si la clase Archivo::MP3 no define el método, pero sí lo hace la clase Archivo, entonces Perl llamará al método de la clase Archivo.

Si Archivo hereda de OrigenDatos, que hereda a su vez de Cosa, entonces Perl deberá subir siguiendo la cadena, si es necesario.

Es posible llamar explícitamente a un método de la clase primaria desde una clase derivada:

package Archivo::MP3;

use parent 'Archivo';

sub imprimir_info {
    my $self = shift;

    $self->SUPER::imprimir_info();
    print "Título: ", $self->titulo, "\n";
}

SUPER:: le indica a Perl que busque el método imprimir_info() en la cadena de herencia de la clase Archivo::MP3. Cuando encuentra la clase primaria que implementa este método, llama al método.

Antes mencionamos la herencia múltiple. El problema de la herencia múltiple es que complica enormemente la resolución de métodos. Consulte perlobj para obtener más información.

Encapsulación

La encapsulación expresa la idea de que los objetos son opacos. Cuando otros desarrolladores usen su clase no necesitarán saber cómo se ha implementado; solo tienen que saber qué es lo que hace.

La encapsulación es importante por varias razones. En primer lugar, permite separar la API pública de la implementación privada. Esto significa que se puede cambiar la implementación sin cambiar la API.

En segundo lugar, cuando las clases están bien encapsuladas se hace más fácil la creación de subclases. Idealmente, una subclase usa las mismas API para acceder a los datos del objeto que las usadas por la clase primaria. En realidad, a veces la creación de subclases requiere infringir el principio de encapsulación, pero si la interfaz es buena, la posibilidad de que esto ocurra es mínima.

Ya se ha mencionado previamente que la mayoría de los objetos Perl se implementan internamente como hashes. El principio de encapsulación nos dice que no deberíamos basarnos en esta característica. En lugar de esto, deberíamos usar métodos de acceso para acceder a los datos del hash. Los sistemas de orientación a objetos que se recomiendan a continuación automatizan la generación de los métodos de acceso. Si usa cualquiera de ellos, no tendrá que acceder directamente al hash.

Composición

Es habitual en el código orientado a objetos que un objeto contenga referencias a otro objeto. Esto se denomina composición, o relación "tiene-un" (has-a en inglés).

Se ha mencionado previamente que en la clase Archivo el método de acceso al miembro hora_ult_mod podría devolver un objeto de la clase DateTime. Este es un ejemplo perfecto de composición. Incluso se puede hacer que los métodos de acceso a ruta y contenido devuelvan también objetos. La clase Archivo estaría compuesta de varios objetos.

Roles

Los roles representan lo que la clase hace, no lo que la clase es. Son relativamente recientes en Perl, pero su uso se ha popularizado. Los roles se aplican a las clases. Se puede decir que las clases consumen roles.

Los roles son una alternativa a la herencia para ofrecer polimorfismo. Supongamos que tenemos dos clases: Radio y Equipo. Ambos aparatos tienen interruptores de encendido/apagado. Queremos expresar esto en las definiciones de las clases.

Podríamos hacer que ambas clases heredasen de una clase primaria común, como Máquina, aunque no todas las máquinas disponen de estos interruptores. Podríamos crear una clase primaria llamada TieneInterruptor, pero sería algo muy artificial. Las radios y los equipos no son casos especiales de esta clase primaria. De hecho, esta clase primaria es más bien ridícula.

Aquí es donde entran en juego los roles. Tiene sentido crear un rol TieneInterruptor y aplicarlo a ambas clases. Este rol podría definir una interfaz conocida con los métodos encender() y apagar().

Perl no dispone de ningún mecanismo para expresar roles. En el pasado, los programadores tenían que resignarse a usar herencia múltiple. Actualmente ya existen varias opciones buenas en CPAN para usar roles.

Cuándo se debe usar la orientación a objetos

La orientación a objetos no es la mejor solución para todos los problemas. En el libro Perl Best Practices (publicado en 2004 por O'Reilly Media, Inc.), Damian Conway proporciona una lista de criterios para decidir si la orientación a objetos se ajusta a nuestro problema:

  • El sistema que se está diseñando es grande o puede llegar a serlo.

  • Los datos se pueden agregar en estructuras obvias, especialmente si hay una gran cantidad de datos en cada agregado.

  • Los distintos tipos de datos agregados forman una jerarquía natural que facilita el uso de la herencia y el polimorfismo.

  • Tiene datos a los que hay que aplicar muchas operaciones diferentes.

  • Es necesario llevar a cabo las mismas operaciones generales sobre tipos de datos relacionados, pero con ligeras variaciones en función del tipo de datos específico al que se aplican estas operaciones.

  • Es probable que tenga que agregar nuevos tipos de datos más adelante.

  • Las interacciones típicas entre elementos de datos se representan mejor mediante operadores.

  • Es probable que la implementación de componentes individuales del sistema cambie con el tiempo.

  • El diseño del sistema ya es orientado a objetos.

  • Muchos programadores van a utilizar sus módulos de código.

SISTEMAS ORIENTADOS A OBJETOS EN PERL

Como ya se ha mencionado antes, el sistema de orientación a objetos de Perl es minimalista, pero también muy flexible. A lo largo de los años, muchas personas han desarrollado sistemas basados en el sistema predefinido de Perl para proporcionar más características y facilidades.

Le recomendamos que use alguno de los sistemas siguientes. Incluso los más sencillos le ahorrarán tener que escribir el mismo código repetidamente. No hay ninguna razón para empezar a escribir clases desde cero.

Si está interesado en conocer los detalles de estos sistemas, consulte perlobj.

Moose

Moose se presenta como un "sistema postmoderno de orientación a objetos para Perl 5". No se asuste, la etiqueta "postmoderno" es una referencia a la descripción de Perl que hizo Larry: "el primer lenguaje de programación postmoderno".

Moose proporciona un completo y moderno sistema de orientación a objetos. Su principal influencia es el sistema de orientación a objetos de Common Lisp, pero también toma ideas de Smalltalk y de otros lenguajes. Moose fue creado por Stevan Little y se basa en su trabajo sobre el diseño de orientación a objetos de Perl 6.

El código de nuestra clase Archivo con Moose sería:

package Archivo;
use Moose;

has ruta         => ( is => 'ro' );
has contenido    => ( is => 'ro' );
has hora_ult_mod => ( is => 'ro' );

sub imprimir_info {
    my $self = shift;

    print "Ruta del archivo: ", $self->ruta, "\n";
}

Moose proporciona diversas características:

  • Simplificación declarativa

    Moose proporciona una capa de simplificación declarativa para definir las clases. Esta simplificación consiste en un conjunto de funciones exportadas que hacen que la declaración de las clases sea más sencilla y agradable. Esto permite describir qué es la clase, en lugar de tener que decir a Perl cómo implementar la clase.

    Los atributos se declaran con la subrutina has() y Moose crea automáticamente los métodos de acceso para los atributos declarados. También se ocupa de crear automáticamente un método new(). Este constructor sabe cuáles son los atributos declarados, por lo que puede establecerlos al crear una nueva instancia de Archivo.

  • Roles predefinidos

    Moose permite definir roles de la misma forma en que se definen las clases:

    package TieneInterruptor;
    use Moose::Role;
    
    has encendido => (
        is  => 'rw',
        isa => 'Bool',
    );
    
    sub encender {
        my $self = shift;
        $self->encendido(1);
    }
    
    sub apagar {
        my $self = shift;
        $self->encendido(0);
    }
  • Un sistema de tipos en miniatura

    En el ejemplo anterior se aprecia que se pasa un valor isa => 'Bool' a has() al crear el atributo encendido. Esto le dice a Moose que este atributo debe ser un valor booleano. Si se intenta asignar un valor no válido el código generará un error.

  • Introspección completa y manipulación

    Las características de introspección predefinidas son mínimas. Moose se basa en ellas y crea una capa completa de introspección para sus clases. Esto permite contestar a preguntas como "¿qué métodos implementa la clase Archivo?". También permite modificar las clases mediante programación.

  • Autocontenido y extensible

    Moose se describe a sí mismo mediante su propia API de introspección. Además de ser un truco ingenioso, significa que puede extender Moose mediante Moose.

  • Ecosistema variado

    Existe un variado ecosistema de extensiones de Moose en CPAN, en el espacio de nombres MooseX. Además, muchos módulos de CPAN ya usan Moose, lo que proporciona muchos ejemplos de los que puede aprender.

  • Muchas más características

    Moose es una herramienta muy poderosa. Aquí solo hemos descrito una pequeña parte de sus características. Le animamos a aprender más mediante la lectura de la documentación de Moose, comenzando con Moose::Manual.

Por supuesto, Moose no es perfecto.

Puede hacer que su código tarde más tiempo en cargar. Moose no es pequeño y genera una gran cantidad de código cuando el usuario define sus propias clases. Esto hace que el código en tiempo de ejecución sea lo más eficiente posible, pero tendrá un coste cuando todo este código se cargue por primera vez.

Este incremento en el tiempo de carga puede ser problemático cuando la velocidad de inicio es importante, como en scripts de línea de comandos o en el típico script CGI que debe cargarse cada vez que se ejecuta.

Antes de asustarse debe saber que mucha gente usa Moose para construir herramientas de línea de comandos y código con necesidades específicas de tiempo de inicio. Le animamos a probar Moose antes de preocuparse por la velocidad de inicio.

Por otra parte, Moose depende de muchos módulos. La mayoría son módulos independientes, algunos generados a partir de Moose. Moose y algunas de sus dependencias requieren un compilador. Si tiene que instalar el software en un sistema sin compilador, o si las dependencias suponen un problema, entonces Moose podría no ser la solución adecuada.

Mouse

Si prueba Moose y encuentra que algunas de estas características impiden su uso, le recomendamos entonces el uso de Mouse. Mouse implementa un subconjunto de la funcionalidad de Moose en un paquete más simple. La interfaz final es la misma para todas las características que implementa, de forma que es posible cambiar de Mouse a Moose de forma sencilla.

Mouse no implementa la mayor parte de la interfaz de introspección de Moose, por lo que la carga de módulos resulta más rápida. Además, todas las dependencias necesarias están incluidas en el núcleo de Perl, de forma que puede ejecutarse sin necesidad de compilador. Si dispone de compilador, Mouse lo usará para compilar parte de su código o bien para aumentar la velocidad.

Por último, incluye el módulo Mouse::Tiny, que consta de la mayoría de las características de Mouse y que se empaqueta en un único archivo de módulo. Puede copiar este archivo de módulo en el directorio de bibliotecas de la aplicación para facilitar su empaquetamiento.

Los autores de Moose esperan que algún día, cuando Moose haya mejorado lo suficiente, Mouse pueda quedar obsoleto, pero de momento proporciona una sólida alternativa a Moose.

Class::Accessor

Class::Accessor es el polo opuesto a Moose. Proporciona muy pocas características y no es autocontenido.

Sin embargo, es muy simple, está programado en Perl puro y no tiene ninguna dependencia externa al núcleo. También proporciona una API "de tipo Moose" para las características que ofrece.

Aunque no le quitará mucho trabajo, es preferible a escribir sus propias clases desde cero.

La clase Archivo con Class::Accessor sería:

package Archivo;
use Class::Accessor 'antlers';

has ruta         => ( is => 'ro' );
has contenido    => ( is => 'ro' );
has hora_ult_mod => ( is => 'ro' );

sub imprimir_info {
    my $self = shift;

    print "Ruta del archivo: ", $self->ruta, "\n";
}

La marca de importación antlers indica a la clase Class::Accessor que desea definir los atributos con el estilo de sintaxis de Moose. El único parámetro que puede pasar a has es is. Le recomendamos el uso del estilo de sintaxis de Moose si elige Class::Accessor, ya que así le resultará más sencillo el trabajo de migración si posteriormente decide usar Moose.

Al igual que Moose, Class::Accessor genera los métodos de acceso y un constructor para la clase.

Object::Tiny

Por último, también puede usar Object::Tiny. Este módulo se ajusta realmente a su nombre. Tiene una interfaz de programación realmente mínima y carece de dependencias (del núcleo o externas). Sin embargo, es mucho más sencillo usar este módulo que escribir código orientado a objetos desde cero.

Nuestra clase Archivo sería:

package Archivo;
use Object::Tiny qw( ruta contenido hora_ult_mod );

sub imprimir_info {
    my $self = shift;

    print "Ruta del archivo: ", $self->ruta, "\n";
}

¡Y ya está!

Con Object::Tiny todos los métodos de acceso son de solo lectura. También genera automáticamente un constructor y todos los métodos de acceso que defina.

Role::Tiny

Como se mencionó con anterioridad, los roles proporcionan un alternativa a la herencia, pero Perl no ofrece esta característica de forma predefinida. Si elige usar Moose, dispondrá de una implementación completa de los roles. Si usa alguno de los otros módulos de orientación a objetos recomendados, también podrá usar roles con Role::Tiny

Role::Tiny ofrece algunas de las características que proporciona el sistema Moose, pero en un paquete mucho más pequeño. En particular, no admite ningún tipo de declaración de atributo, por lo que tendrá que declararlos a mano. Aun así es útil y funciona bien con Class::Accessor y Object::Tiny

Resumen de sistemas de orientación a objetos

A continuación se ofrece un breve resumen de las opciones consideradas:

  • Moose

    Moose es la opción máxima (la más completa). Dispone de muchas características, un gran ecosistema y una importante base de usuarios. También se ha descrito brevemente Mouse. Mouse es una versión reducida de Moose que ofrece una alternativa razonable cuando Moose no es adecuado para su aplicación.

  • Class::Accessor

    Class::Accessor es un sistema mucho más reducido que Moose, pero ofrece una alternativa interesante cuando Moose resulta excesivo. Se ha utilizado durante mucho tiempo y está bien probado. También ofrece un modo de compatibilidad mínima con Moose que facilita la migración desde Class::Accessor a Moose.

  • Object::Tiny

    Object::Tiny es la opción más minimalista. No presenta dependencias y casi no hay sintaxis que aprender. Es una buena opción para entornos reducidos y para crear un programa rápidamente sin preocuparse de los detalles.

  • Role::Tiny

    Use Role::Tiny con Object::Tiny o Class::Accessor si desea usar herencia múltiple. Si se decanta por Moose, podrá disponer de su implementación de roles.

Otros sistemas de orientación a objetos

En CPAN encontrará decenas de módulos relacionados con la orientación a objetos, además de los considerados aquí; es posible que se encuentre con varias de estas alternativas si trabaja con código de otras personas.

Además, existe mucho código en el que se usa orientación a objetos "a mano", basado en las características de orientación a objetos predefinidas de Perl. Si necesita mantener este tipo de código, debería leer perlobj para comprender exactamente cómo funciona la orientación a objetos ofrecida por Perl.

CONCLUSIÓN

Como se indicó con anterioridad, el sistema de orientación a objetos de Perl es minimalista y esto ha hecho que surgieran muchos sistemas de programación orientada a objetos en CPAN. Aunque puede prescindir de estos sistemas modernos y escribir sus propias clases a mano, no es necesario hacerlo con las versiones modernas de Perl.

Para sistemas pequeños, tanto Object::Tiny como Class::Accessor ofrecen sistemas minimalistas que se ocupan de las tareas repetitivas y simplifican el trabajo.

Para proyectos más complejos, Moose proporciona un variado conjunto de características que le permitirán centrarse en la implementación de la lógica del sistema.

Le recomendamos que pruebe Moose, Class::Accessor y Object::Tiny para decidir qué sistema de orientación a objetos le conviene más.

TRADUCTORES

  • Manuel Gómez Olmedo

  • Joaquín Ferrero (Tech Lead)

  • Enrique Nell (Language Lead)