index | project | pods | responsabili


NOME

perlootut - Tutorial sulla Programmazione ad Oggetti in Perl


DATA

Questo documento è stato creato nel febbraio 2011.


DESCRIZIONE

Questo documento fornisce un'introduzione alla programmazione orientata agli oggetti in Perl. Si comincia con una breve panoramica dei concetti che stanno dietro alla progettazione orientata agli oggetti. Poi vengono introdotti diversi sistemi OO presi da L <CPAN|http://search.cpan.org> che si basano su ciò che offre Perl.

Di default, il sitema OO [Orientato agli Oggetti, NdT] integrato in Perl è assai minimale, lasciando fare a voi la maggior parte del lavoro. Questo minimalismo aveva parecchio senso nel 1994, ma negli anni successivi a Perl 5.0 si è visto emergere un certo numero di modelli comuni nella OO di Perl. Fortunatamente, la flessibilità di Perl ha permesso la fioritura di un ricco ecosistema di sistemi Perl per l'OO.

Se si vuole sapere come funziona la OO del Perl dietro le quinte, perlobj spiega tutti i dettagli.

Questo documento presuppone che siate già in grado di capire le basi del Perl, la sintassi, i tipi di variabili, gli operatori e le chiamate a subroutine. Se non si comprendono ancora questi concetti, vi preghiamo di leggere prima perlintro. Dovreste anche leggere perlsyn, perlop e perlsub.


FONDAMENTI DELL'ORIENTAMENTO AGLI OGGETTI

La maggior parte dei sistemi OO condividono una serie di concetti comuni. Probabilmente avete giè sentito termini come ``classe'', ``oggetto'', metodo `` e ''attributo``. La comprensione dei concetti renderà molto più facile leggere e scrivere codice orientato agli oggetti. Se avete già familiarità con questi termini, si dovrebbe comunque sfogliare questa sezione, dal momento che spiega ogni concetto in termini dell'implementazione OO di Perl.

Il sistema OO di Perl è basato sulle classi. L'OO basato sulle classi è abbastanza comune. È utilizzato da Java, C++, C#, Python, Ruby e molti altri linguaggi. Ci sono anche altri paradigmi di orientamento agli oggetti. JavaScript è il linguaggio più popolare che usa un altro paradigma. Il sistema OO di JavaScript è basato sui prototipi.

Oggetto

Un oggetto è una struttura dati che raggruppa insieme dati e subroutine che operano su tali dati. I dati di un oggetto si chiamano attributi e le sue subroutine sono chiamate metodi. Un oggetto può essere pensato come ad un nome (una persona, un servizio web, un computer).

Un oggetto rappresenta una singola cosa discreta. Ad esempio, un oggetto potrebbe rappresentare un file. Gli attributi di un oggetto file potrebbero includere il suo percorso, il contenuto e la data dell'ultima modifica. Se abbiamo creato un oggetto per rappresentare /etc/hostname su una macchina chiamata ``pippo.esempio.com'', il percorso di questo oggetto sarebbe ``/etc/hostname'', il suo contenuto sarebbe ``pippo\n'' e la data dell'ultima modifica sarebbero 1304974868 secondi dall'inizio dell'epoch.

I metodi associati ad un file potrebbero includere rename() e write().

In Perl, la maggior parte degli oggetti sono hash, ma i sistemi OO che consigliamo vi preservano dal dover preoccuparsi di questo aspetto. In pratica, è meglio considerare la struttura dati interna di un oggetto non trasparente.

Classe

Una classe definisce il comportamento di una categoria di oggetti. Una classe è un nome di una categoria (come ``File'') e una classe definisce anche il comportamento degli oggetti di quella categoria.

Tutti gli oggetti appartengono ad una classe specifica. Ad esempio, il nostro oggetto /etc/hostname appartiene alla classe File. Quando vogliamo creare uno specifico oggetto, si comincia con la sua classe e costruiamo o istanziamo un oggetto. Un oggetto specifico viene spesso indicato come istanza di una classe.

In Perl, un package può essere una classe. La differenza tra un package che è una classe e uno che non lo è si basa su come viene utilizzato il package. Ecco la nostra ``dichiarazione di classe'' per la classe File:

  package File;

In Perl, non vi è alcuna parola chiave speciale per costruire un oggetto. Tuttavia, la maggior parte dei moduli OO su CPAN utilizzano un metodo denominato new() per costruire un nuovo oggetto:

  my $nome_host = File-> new (
       percorso             => '/etc/hostname',
       contenuto            => "pippo\n",
       data_ultima_modifica => 1304974868,
  );

(Non vi preoccupate riguardo all'operatore ->, verrà spiegato in seguito).

Blessing

Come abbiamo detto in precedenza, la maggior parte degli oggetti in Perl sono hash, ma un oggetto può essere un'istanza di qualsiasi tipo di dato (scalare, array, ecc.). Trasformare una semplice struttura dati in un oggetto viene fatto eseguendo un blessing di quella struttura dati utilizzando la funzione Perl bless.

Sebbene vi raccomandiamo vivamente di non costruire i vostri oggetti da zero, si dovrebbe conoscere il termine bless. Una struttura dati blessed (conosciuta anche come ``referente'') è un oggetto. A volte diciamo che un oggetto è stato ``blessed into a class'', ovvero sottoposto a bless di quella classe.

Una volta che un referente è stato sottoposto a bless, la funzione blessed del modulo core [appartenente ai moduli base, presenti da subito nell'installazione perl, NdT] the Scalar::Util manpage è in grado di dirci il nome della sua classe. Questa subroutine restituisce la classe di un oggetto quando le viene passato un oggetto, falso altrimenti.

  use Scalar::Util 'blessed';
  print blessed($hash);       # undef
  print blessed($nome_host);  # File

Costruttore

Un costruttore crea un nuovo oggetto. In Perl, il costruttore di una classe è solo un altro metodo, a differenza di altri linguaggi che forniscono la sintassi per i costruttori. La maggior parte della classi in Perl utilizza new come nome per il proprio costruttore:

  my $file = File->new(...);

Metodi

Avete già imparato che un metodo è una subroutine che opera su un oggetto. Si può pensare ad un metodo come le cose che un oggetto può fare. Se un oggetto è un nome, allora i metodi sono i suoi verbi (salvare, stampare, aprire).

In Perl, i metodi sono semplicemente subroutine che risiedono nel pacchetto di una classe. I metodi sono sempre scritti per ricevere l'oggetto come proprio primo argomento:

  sub stampa_info {
      my $self = shift;
      print "Questo file sta in ", $self->percorso, "\n";
  }
  $file->stampa_info;
  # Il file sta in /etc/hostname

Cosa rende un metodo speciale è il modo in cui viene chiamato. L'operatore freccia (->) dice a Perl che stiamo chiamando un metodo.

Quando facciamo una chiamata al metodo, Perl stabilisce che il metodo invocant sia passato come primo argomento. Invocant è un nome di fantasia che indica la cosa sul lato sinistro della freccia. Invocant può essere una classe, un nome o un oggetto. Possiamo anche passare al metodo degli argomenti aggiuntivi:

  sub stampa_info {
      my $self   = shift;
      my $prefisso = shift // "Questo file sta in ";
      print $prefisso, ", ", $self->percorso, "\n";
  }
  $file->stampa_info("Il file e` posizionato in ");
  # Il file e` posizionato in /etc/hostname

Attributi

Ogni classe può definire i suoi attributi. Quando istanziamo un oggetto, assegniamo i valori di tali attributi. Ad esempio, ogni oggetto File ha un percorso. Gli attributi vengono a volte chiamati proprietà.

Perl non ha alcuna sintassi speciale per gli attributi. Dietro le quinte, gli attributi sono spesso memorizzati come chiavi del (sottostante) hash che è l'oggetto, ma non ci si deve preoccupare di questo aspetto.

Si consiglia di accedere agli attributi solo tramite metodi accessor. Questi sono metodi che possono ottenere o impostare il valore di ogni attributo. L'abbiamo visto in precedenza nell'esempio stampa_info(), che chiama $self->percorso.

Si potrebbe anche incontrare i termini getter e setter. Questi sono due tipi di accessor. Un getter ottiene il valore dell'attributo, mentre un setter lo imposta. Un altro termine per un setter è mutator.

Gli attributi sono solitamente definiti come di sola lettura o di lettura e scrittura. Gli attributi di sola scrittura possono essere impostati solo quando l'oggetto viene creato, mentre gli attributi di lettura-scrittura possono essere modificati in qualsiasi momento.

Il valore di un attributo può essere esso stesso un altro oggetto. Per esempio, invece di restituire il suo istante di ultima modifica come un numero, la classe File potrebbe restituire un oggetto DateTime che rappresenta quel valore.

È possibile avere una classe che non espone pubblicamente attributi impostabili. Non tutte le classi hanno attributi e metodi.

Polimorfismo

Il polimorfismo è un modo elegante per dire che gli oggetti provenienti da due diverse classi condividono delle API. Per esempio, potremmo avere le classi File e PaginaWeb che hanno entrambi un metodo stampa_contenuto(). Questo metodo potrebbe produrre un output diverso per ogni classe, ma le classi condividono un'interfaccia comune.

Mentre le due classi possono differire in molti modi, per quanto riguarda il metodo stampa_contenuto(), sono la stessa cosa. Questo significa che possiamo tentare di chiamare il metodo stampa_contenuto() su un oggetto di entrambe le classi, e non c'è bisogno di sapere a quale classe l'oggetto appartiene!.

Il polimorfismo è uno dei concetti chiave della progettazione orientata agli oggetti.

Ereditarietà

L'ereditarietà consente di creare una versione specializzata di una classe esistente. L'ereditarietà consente alla nuova classe di riutilizzare i metodi e gli attributi di un'altra classe.

Ad esempio, potremmo creare una classe File::MP3 che eredita da File. Un File::MP3 è-una (is-a) versione più specifica di File. Tutti i file mp3 sono file, ma non tutti i file sono file mp3.

Si fa spesso riferimento a relazioni di ereditarietà come relazioni genitore-figlio o superclasse/sottoclasse. A volte diciamo che il figlio ha un rapporto is-a (è-un) con la sua classe genitore.

File è una superclasse di File::MP3 e File::MP3 è una sottoclasse di File.

  package File::MP3;
  use parent 'File';

Il modulo parent [genitore, NdT] è uno dei diversi modi con i quali Perl vi consente di definire rapporti di ereditarietà.

Perl permette l'ereditarietà multipla, il che significa che una classe può ereditare da genitori multipli. Sebbene questo sia possibile, si sconsiglia vivamente di farlo. Generalmente, è possibile utilizzare ruoli per fare tutto ciò che si può fare con l'ereditarietà multipla, ma in un modo più pulito.

Si noti che non c'è niente di sbagliato con la definizione di sottoclassi multiple di una determinata classe. Questa è una prassi usuale e sicura. Ad esempio, potremmo definire le classi File::MP3::FixedBitrate e File::MP3::VariableBitrate per distinguere diversi tipi di file mp3.

Override [ridefinizione, NdT] dei metodi e risoluzione dei metodi

L'ereditarietà consente a due classi di condividere il codice. Di default, ogni metodo nella classe genitore è disponibile anche nella classe figlio. Il figlio può esplicitamente fare un override del metodo di un genitore per fornire la propria implementazione. Per esempio, se abbiamo un oggetto File::MP3, possiede il metodo stampa_info() da File:

  my $gabbia = File::MP3->new(
      percorso             => 'mp3s/My-Body-Is-a-Cage.mp3',
      contenuto            => $dati_mp3,
      data_ultima_modifica => 1304974868,
      titolo               => 'My Body Is a Cage', # Il Mio Corpo E` una Gabbia
  );
  $gabbia->stampa_info;
  # Il file sta in mp3s/My-Body-Is-a-Cage.mp3

Se volessimo includere il titolo dell'mp3 nella presentazione????, potremmo effettuare l'override del metodo:

  package File::MP3;
  use parent 'File';
  sub stampa_info {
      my $self = shift;
      print "Questo file sta in ", $self->percorso, "\n";
      print "Il suo titolo e` ", $self->titolo, "\n";
  }
  $gabbia->stampa_info;
  # Il file sta in mp3s/My-Body-Is-a-Cage.mp3
  # Il suo titolo e` My Body Is a Cage

Il processo di determinazione su quale metodo dovrebbe essere usato, viene chiamato metodo di risoluzione. Cosa fa Perl è guardare prima la classe dell'oggetto (in questo caso File::MP3). Se questa classe definisce il metodo, allora viene chiamata tale versione della classe del metodo. In caso contrario, Perl cerca a sua volta in ogni classe genitore. Per File::MP3, il suo solo genitore è File. Se File::MP3 non definisce il metodo, ma è File che lo fa, allora Perl chiama il metodo in File.

Se File eredita da SorgenteDati, la quale ha ereditato da Cosa, allora Perl, se necessario, continuerebbe a cercare ``lungo la catena''.

È possibile chiamare in modo esplicito un metodo genitore da un figlio:

  package File::MP3;
  use parent 'File';
  sub stampa_info {
      my $self = shift;
      $self->SUPER::stampa_info();
      print "Il suo titolo e` ", $self->titolo, "\n";
  }

La parte SUPER:: dice a Perl di cercare stampa_info() nella catena di ereditarietà della classe File::MP3. Quando trova la classe genitore che implementa tale metodo, il metodo viene chiamato.

Abbiamo accennato in precedenza all'ereditarietà multipla. Il problema principale con l'ereditarietà multipla è che complica notevolmente il metodo di risoluzione. Per maggiori dettagli si veda perlobj.

Incapsulamento

L'incapsulamento è l'idea che un oggetto sia non trasparente. Quando un altro sviluppatore utilizza la vostra classe, non ha bisogno di sapere come è stata implementata, ha solo bisogno di sapere che cosa fa.

L'incapsulamento è importante per diverse ragioni. In primo luogo, permette di separare le API pubbliche dall'implementazione privata. Ciò significa che potete cambiare questa implementazione senza violare le API.

In secondo luogo, quando le classi sono ben incapsulate, per loro diventa più facile divenire una sottoclasse. Idealmente, una sottoclasse utilizza le stesse API di accesso ai dati degli oggetti che utilizzano la sua classe genitore. In realtà, fare una sottoclasse a volte implica la violazione dell'incapsulamento, ma delle buone API possono minimizzare la necessità di farlo.

Abbiamo accennato in precedenza che, dietro le quinte, in Perl molti oggetti sono implementati come hash. Il principio di incapsulamento ci dice che non dovremmo farvi affidamento. Invece, per accedere ai dati contenuti in questo hash dovremmo usare gli accessor dei metodi. Tutti i sistemi ad oggetti che vi consigliamo qui di seguito, automatizzano la generazione degli accessor dei metodi. Se ne usate uno, non dovreste mai accedere direttamente all'oggetto come hash.

Composizione

Nel codice orientato agli oggetti, spesso ci si accorge che un oggetto fa riferimento ad un altro oggetto. Questo si chiama composizione oppure relazione has-a [ha-un, NdT].

In precedenza abbiamo detto che l'accessor data_ultima_modifica della classe File potrebbe restituire un oggetto DateTime. Questo è un perfetto esempio di composizione. Potremmo andare anche oltre, e far sì che anche gli accessor percorso e contenuto restituiscano oggetti. La classe File sarebbe poi composta da diversi altri oggetti.

Ruoli

Un ruolo è qualcosa che una classe fa, piuttosto che qualcosa che <è>. I ruoli sono relativamente nuovi per Perl, ma sono diventati molto popolari. I ruoli sono applicati alle classi. A volte si dice che le classi consumano i ruoli.

I ruoli sono un'alternativa all'ereditarietè per fornire il polimorfismo. Supponiamo di avere due classi, Radio e Computer. Entrambi questi oggetti hanno interruttori on/off. Vogliamo modellare questo aspetto nelle definizioni della nostra classe.

Avremmo potuto ereditare entrambe le classi da un progenitore comune, come Macchina, ma non tutte le macchine hanno interruttori on/off. Si potrebbe creare una classe genitore chiamata HaInterruttoriOnOff, che però è molto artificioso. Le radio e computer non sono specializzazioni di questo genitore. Questo genitore è in realtà una creazione piuttosto ridicola.

Questo è il caso nel quale i ruoli fanno la loro comparsa. Ha molto senso creare un ruolo HaInterruttoriOnOff e applicarlo ad entrambe le classi. Questo ruolo definirebbe delle API note, come il fornire i metodi premi_on() e premi_off().

Perl non ha alcuna modalità integrata per esprimere i ruoli. In passato, le persone stringevano semplicemente i denti ed utilizzavano l'ereditarietà multipla. Oggigiorno, ci sono diverse buone scelte su CPAN per l'utilizzo dei ruoli.

Quando Utilizzare l'OO

L'Orientamento agli Oggetti non è la migliore soluzione per ogni problema. In Perl Best Practices (copyright 2004, pubblicato da O'Reilly Media, Inc.), Damian Conway fornisce un elenco di criteri da utilizzare per decidere se l'OO è la giusta scelta per il vostro problema:

  • Il sistema in fase di progettazione è grande o rischia di diventare grande.

  • I dati possono essere aggregati in strutture palesi, specialmente se c'è una grande quantità di dati in ciascun aggregato.

  • I vari tipi di dati aggregati formano una gerarchia naturale che facilita l'utilizzo di ereditarietà e polimorfismo.

  • Si ha una parte di dati su cui possono essere applicate varie differenti operazioni.

  • È necessario eseguire le stesse generiche operazioni su tipi di dati correlati, ma con lievi variazioni a seconda del tipo specifico di dati a cui sono applicate le operazioni.

  • È probabile che in seguito si dovrà aggiungere nuovi tipi di dati.

  • Le interazioni tipiche tra le parti di dati sono rappresentate meglio da operatori.

  • L'implementazione dei singoli componenti del sistema può cambiare nel tempo.

  • Il design del sistema è già orientato agli oggetti.

  • Un gran numero di altri programmatori useranno il codice dei vostri moduli.


SISTEMI OO IN PERL

Come abbiamo accennato in precedenza, il sitema OO integrato in Perl è minimale, ma anche abbastanza flessibile. Nel corso degli anni, molte persone hanno sviluppato sistemi che si basano sul sitema OO integrato in Perl per fornire maggiori funzionalità e vantaggi.

Si consiglia vivamente di utilizzare uno di questi sistemi. Anche il più minimale di questi elimina molto di quel codice ripetitivo che fa sempre le stesse cose. In Perl non c'è davvero nessun buon motivo per scrivere le classi da zero.

Se siete interessati alle interiora che sono alla base di questi sistemi, date un'occhiata a perlobj.

Moose

Moose si pubblicizza come un ``sistema postmoderno di oggetti per Perl 5''. Non abbiate paura, l'etichetta ``postmoderno'' è un richiamo alla descrizione di Larry sul Perl quale ``primo linguaggio postmoderno per computer''.

Moose fornisce un completo e moderno sistema OO. La sua più grande influenza è stata il sistema ad oggetti del Common Lisp, ma ha preso in prestito anche idee dallo Smalltalk e da molti altri linguaggi. Moose è stato creato da Stevan Little e richiama fortemente il suo lavoro sul design OO di Perl 6.

Ecco la nostra classe File utilizzando Moose:

  package File;
  use Moose;
  has percorso             => ( is => 'ro' ); # ['ro' sta per Read Only, di sola lettura, NdT]
  has contenuto            => ( is => 'ro' );
  has data_ultima_modifica => ( is => 'ro' );
  sub stampa_info {
      my $self = shift;
      print "Questo file sta in ", $self->percorso, "\n";
  }

Moose fornisce una serie di funzionalità:

  • Zucchero dichiarativo
    Moose fornisce un livello di ``zucchero'' dichiarativo per la definizione delle classi. Questo zucchero è solo un insieme di funzioni esportate che rendono più semplice e gradevole la dichiarazione di come funziona la vostra classe. Questo consente di descrivere cosa la classe è, piuttosto che dover dire a Perl come implementare una classe.

    La subroutine has() dichiara un attributo e Moose crea automaticamente gli accessor per questi attributi. Si prende anche cura di creare per voi un metodo new(). Questo costruttore conosce gli attributi che avete dichiarato, in modo da poterli impostare quando si crea un nuovo File.

  • Ruoli integrati
    Moose consente di definire i ruoli allo stesso modo in cui si definiscono le classi:
      package HaInterruttoriOnOff;
      use Moose::Role;
      has is_on => (
          is  => 'rw',
          isa => 'Bool',
      );
      sub premi_on {
          my $self = shift;
          $self->is_on(1);
      }
      sub premi_off {
          my $self = shift;
          $self->is_on(0);
      }

  • Un sistema con tipizzazione, in miniatura
    Nell'esempio qui sopra, potete vedere che abbiamo passato isa => 'Bool' a has() nel momento in cui abbiamo creato l'attributo is_on. Ciò dice a Moose che questo attributo deve essere un valore booleano. Se si tenta di impostarlo ad un valore non valido, il codice genererà un errore.

  • Completa autoanalisi???? e manipolazione
    Le caratteristiche di autonalisi integrate in Perl sono abbastanza ridotte. Moose si basa su di esse e crea un completo strato di autoanalisi per le vostre classi. Questo consente di porre domande come ``che metodi implementa la classe File?''. Inoltre, consente di modificare le vostre classi passo passo????.

  • Self-hosted [in grado di modificare esso stesso le proprie funzionalità, NdT] ed estensibile
    Moose descrive se stesso utilizzando le sue proprie API d'autoanalisi. Oltre ad essere un trucco fico, questo significa che è possibile estendere Moose utilizzando Moose stesso.

  • Ricco ecosistema
    C'è un ricco ecosistema di estensioni Moose su CPAN, all'interno del namespace MooseX. Inoltre, molti moduli su CPAN utilizzano già Moose, fornendovi un sacco di esempi da cui imparare.

  • Molte altre funzioni
    Moose è uno strumento molto potente, e non possiamo spiegare qui tutte le sue caratteristiche. Vi incoraggiamo a saperne di più leggendo la documentazione di Moose, iniziando con Moose::Manual.

Naturalmente, Moose non è perfetto.

Moose può rendere il vostro codice più lento da caricare. Moose in sé non è piccolo, e quando si definisce una classe genera molto codice. Questa generazione di codice indica che il vostro codice a runtime è veloce come più non potrebbe essere????, ma questo si paga nel momento in cui i moduli vengono caricati per la prima volta.

L'impatto di questo tempo di caricamento può essere un problema quando la velocità di avvio è importante, ad esempio con uno script a riga di comando o uno script CGI standard che deve essere caricato ogni volta che viene eseguito.

Prima di farsi prendere dal panico, sappiate che molte persone usano Moose per degli strumenti a riga di comando e altro codice il cui tempo di caricamento ha una rilevanza importante. Vi incoraggiamo a provare Moose prima di preoccuparsi della velocità di avvio.

Moose ha anche diverse dipendenze da altri moduli. La maggior parte di questi sono piccoli moduli a sé stanti, alcuni dei quali sono stati scorporati da Moose. Moose stesso, e alcune delle sue dipendenze, richiedono un compilatore. Se è necessario installare il vostro software su un sistema senza compilatore, o se avere qualche dipendenza è un problema, allora Moose potrebbe non essere adatto a voi.

Mouse

Se si prova Moose e si scopre che uno di questi problemi vi impedisce il suo utilizzo, vi invitiamo in seguito a considerare Mouse. Mouse implementa un sottoinsieme di funzionalità di Moose in un package più semplice. Per tutte le funzionalità che implementa, le API per l'utente finale sono identiche a quelle di Moose, ciò significa che è possibile passare da Mouse a Moose abbastanza facilmente.

Mouse non implementa la maggior parte delle API di autoanalisi di Moose, risultando così essere spesso pił veloce durante il caricamento dei moduli. Inoltre, tutte le dipendenze di cui ha bisogno fanno parte di quelle fornite nell'installazione base di Perl, e può essere eseguito senza un compilatore. Se si dispone di un compilatore, Mouse lo userà per compilare una parte del suo codice al fine di ottenere un incremento di velocità.

Infine, viene fornito con un modulo Mouse::Tiny che prende la maggior parte delle caratteristiche di Mouse e le impacchetta in un modulo composto da un singolo file. È possibile copiare questo modulo nella directory di libreria della vostra applicazione per rendere agevole la costruzione di un unico pacchetto.

Gli autori di Moose sperano che un giorno Mouse possa essere reso obsoleto dalle sufficienti migliorie di Moose, ma per ora fornisce una utile alternativa a Moose.

Class::Accessor

the Class::Accessor manpage è l'antitesi di Moose. Fornisce pochissime funzionalità e non è self-hosted.

Tuttavia è molto semplice, è scritto in puro e semplice Perl, e non ha dipendenze che non siano moduli già presenti nell'installazione base di Perl. Esso fornisce anche delle API ``a-la Moose'', su richiesta per le funzionalità supportate????.

Anche se non fa molte cose, è ancora preferibile allo scrivere la vostra classe da zero.

Ecco la nostra classe File con Class::Accessor:

  package File;
  use Class::Accessor 'antlers';
  has percorso             => ( is => 'ro' );
  has contenuto            => ( is => 'ro' );
  has data_ultima_modifica => ( is => 'ro' );
  sub stampa_info {
      my $self = shift;
      print "Questo file sta in ", $self->percorso, "\n";
  }

Il parametro di importazione antlers dice a Class::Accessor che si desidera definire gli attributi utilizzando una sintassi simile a quella di <Moose>. L'unico parametro che è possibile passare a has è is. Se si sceglie Class::Accessor, si consiglia di utilizzare questa sintassi a-la Moose perché renderà il percorso di aggiornamento più agevole se in seguito si deciderà di passare a Moose.

Come Moose, Class::Accessor genera per la classe i metodi accessors e un costruttore.

Object::Tiny

Infine, abbiamo the Object::Tiny manpage. Questo modulo è davvero degno del suo nome. Ha delle API incredibilmente minimali e assolutamente senza dipendenze (core o meno). Tuttavia, pensiamo che sia molto più facile da usare rispetto alla scrittura da zero del proprio codice OO.

Ecco ancora una volta la nostra classe File:

  package File;
  use Object::Tiny qw( percorso contenuto data_ultima_modifica );
  sub stampa_info {
      my $self = shift;
      print "Questo file sta in ", $self->percorso, "\n";
  }

Questo è tutto!

Con Object::Tiny, tutti gli accessors sono di sola lettura. Genera un costruttore, così come gli accessors che definite.

Role::Tiny

Come abbiamo accennato prima, i ruoli forniscono un'alternativa all'ereditarietà, ma Perl non ha alcun supporto integrato per i ruoli. Se si sceglie di utilizzare Moose, esso è dotato di una implementazione dei ruoli sviluppata in modo completo. Tuttavia, se si utilizza uno degli altri moduli OO che abbiamo raccomandato, è comunque possibile utilizzare i ruoli con the Role::Tiny manpage.

Role::Tiny offre alcune delle stesse caratteristiche come il sistema di ruoli di Moose, ma in un package molto più piccolo. Si noti in particolare, che non supporta qualsiasi tipo di dichiarazione degli attributi, quindi bisogna farle a mano. Eppure, è utile e funziona bene con Class::Accessor e Object::Tiny.

Sommario dei Sistemi OO

Ecco un breve riassunto delle alternative che abbiamo affrontato:

Moose è l'alternativa ideale. Ha un sacco di funzioni, un grande ecosistema, e una base di utenti fiorente. Abbiamo anche affrontato brevemente Mouse. Mouse è un Moose più leggero, e un'alternativa ragionevole quando Moose non è adatto alla vostra applicazione.

Class::Accessor fa molte meno cose di Moose, ed è una bella alternativa se si trova Moose opprimente. È in giro da lungo tempo ed <Egrave> ben collaudato sul campo di battaglia. Ha anche una minima compabilit<agrave> con Moose che rende facile il passaggio da Class::Accessor a Moose.

Object::Tiny è in assoluto l'alternativa minimale. Non ha dipendenze, e non ha quasi alcuna sinstassi da imparare. È una buona scelta per un ambiente ridotto all'osso e per mettere assieme qualcosa rapidamente senza doversi preoccupare dei dettagli.

Usate Role::Tiny con <Class::Accessor> o Object::Tiny se ci si ritrova a dover tenere conto dell'ereditarietà multipla. Se si passa a Moose, possiede la sua propria implementazione dei ruoli????.

Altri Sistemi OO

Ci sono letteralmente dozzine di altri moduli su CPAN relativi alla OO, oltre a quelli di cui ci si è occupati qui, ed è probabile imbattersene in diversi altri se si lavora con il codice di altre persone.

Inoltre, in un sacco di codice attualmente in produzione tutto l'OO è scritto ``a mano'', utilizzando solo le funzionalità OO integrate in Perl. Se avete bisogno di manutenere tale codice, dovreste leggere perlobj per capire esattamente come funziona l'OO integrato in Perl.


CONCLUSIONE

Come detto precedentemente, il sistema minimale per l'OO di Perl ha portato ad una profusione di sistemi OO su CPAN. Sebbene si possa ancora arrivare all'osso e scrivere le proprie classi a mano, non c'è alcuna ragione per non scriverle con modern Perl.

Per piccoli sistemi, sia the Object::Tiny manpage che the Class::Accessor manpage forniscono entrambi dei sistemi minimali ad oggetti che si prendono cura per voi delle solite cose basilari.

Per i progetti più grandi, Moose fornisce un ricco insieme di funzionalità che consentono di concentrarsi sull'implementazione della logica applicativa.

Vi invitiamo a valutare e giocare con Moose, the Class::Accessor manpage e the Object::Tiny manpage per capire quale sia per voi il sistema OO più appropriato.


TRADUZIONE

Versione

La versione su cui si basa questa traduzione è ottenibile con:

   perl -MPOD2::IT -e print_pod perlootut

Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .

Traduttore

Traduzione a cura di dree.

Revisore

Revisione a cura di .


Mon Jun 11 22:02:20 2012