index | project | pods | responsabili

NOME

perlobj - Gli oggetti in Perl


DESCRIZIONE

Prima di tutto bisogna capire cosa sono i riferimenti in Perl. Per fare ciò si consulti perlref. In secondo luogo, se si trova ancora troppo complicata la guida di riferimento che ci si avvia a leggere, si può trovare un tutorial sulla programmazione orientata agli oggetti in Perl in perltoot e perltooc.

Se si sta ancora leggendo, qui ci sono tre definizioni molto semplici che si dovrebbero trovare rassicuranti.

  1. Un oggetto è semplicemente un riferimento che sa a quale classe esso appartiene.

  2. Una classe è semplicemente un package che fornisce metodi per trattare con i riferimenti ad oggetti.

  3. Un metodo è semplicemente una subroutine che si aspetta il riferimento ad un oggetto (o un nome di package, per i metodi di classe) come primo argomento.

Ora si tratteranno questi punti con maggiore profondità.

Un Oggetto è Semplicemente un Riferimento

Diversamente da ciò che accade in C++, Perl non fornisce una sintassi speciale per i costruttori. Un costruttore è solamente una subroutine che restituisce un riferimento a qualcosa di ``blessed'' [letteralmente ``benedetto'', si intende sottoposto alla funzione bless, NdT] in una classe, generalmente la classe nella quale la subroutine è definita. Ecco un tipico costruttore:

    package Creatura;
    sub new { bless {} }

La parola new non è speciale. Il costruttore si sarebbe potuto scrivere anche in questo modo:

    package Creatura;
    sub nasci { bless {} }

Questo potrebbe persino essere preferibile, poiché i programmatori C++ non saranno indotti a pensare che new funzioni in Perl come fa in C++. Non lo fa. Si raccomanda di dare un nome ai propri costruttori con qualsiasi cosa abbia senso nel contesto del problema che si sta risolvendo. Per esempio, i costruttori dei moduli Tk sono chiamati come i widget che costruiscono.

Una cosa che differisce tra i costruttori in Perl rispetto a quelli in C++ è, che in Perl, devono allocarsi la propria memoria. (L'altra cosa è che non chiamano automaticamente i costruttori della classe base ridefiniti). {} alloca un hash anonimo che non contiene coppie chiave/valore, e lo restituisce. bless() prende quel riferimento e dice all'oggetto che esso referenzia che ora è una Creatura, e restituisce il riferimento stesso. Ciò è fatto per convenienza, perché l'oggetto referenziato sa di essere stato sottoposto a bless, e si potrebbe restituire direttamente il riferimento, come in questo caso:

    sub new {
        my $self = {};
        bless $self;
        return $self;
    }

Spesso si vedono cose del genere in costruttori più complicati che vogliono chiamare metodi della classe come parte della costruzione:

    sub new {
        my $self = {};
        bless $self;
        $self->initialize(); # inizializza(), NdR
        return $self;
    }

Se si ha a cuore l'ereditarietà (e si dovrebbe; si veda perlmodlib/``Modules: Creation, Use, and Abuse'' [``Moduli: Creazione, Uso ed Abuso''>, NdT]) allora si può utilizzare la forma a due argomenti di bless, in modo che i costruttori possano essere ereditati:

    sub new {
        my $class = shift;
        my $self = {};
        bless $self, $class;
        $self->initialize();
        return $self;
    }

Oppure, se ci si aspetta che non venga usato solamente <CLASSE-new() >> ma anche $oggetto->new(), allora si utilizzi qualcosa di simile a ciò che segue. (Va notato che utilizzare questo modo per chiamare new() in un'istanza, non ne fa automaticamente una copia. Se si vuole una copia di un oggetto superficiale [``shallow'', copia del solo oggetto, NdT] o in profondità [``deep'', copia dell'oggetto e di quanto da lui riferito, NdT], allora si dovrebbe permetterlo specificatamente). Il metodo initialize() utilizzato, sarà di una qualsiasi classe $classe nella quale si abbia sottoposto l'oggetto a bless:

    sub new {
        my $this = shift;
        my $class = ref($this) || $this;
        my $self = {};
        bless $self, $class;
        $self->initialize();
        return $self;
    }

All'interno dei package della classe, i metodi avranno a che fare in genere con i riferimenti come con i classici riferimenti. Fuori dal package della classe, il riferimento è generalmente trattato come un valore opaco che è accessibile solo attraverso i metodi della classe.

Sebbene un costruttore possa in teoria rieffettuare il bless di un oggetto referenziato appartenente in quel momento ad un'altra classe, quasi sicuramente ciò è fonte di guai. La nuova classe ha la responsabilità di chiudere in maniera pulita ogni operazione relativa all'oggetto. Il bless precedente viene dimenticato, poiché un oggetto può appartenere ad una sola classe alla volta. (Anche se, naturalmente, esso è libero di ereditare metodi da molte classi). Ad ogni modo, se ci si trova a doverlo fare, la parent class [``classe genitore'', NdT] avrà probabilmente un comportamento improprio.

Un precisazione: gli oggetti in Perl sono sottoposti a bless. I riferimenti no. Gli oggetti sanno a quale package appartengono. I riferimenti no. La funzione bless() usa il riferimento per trovare l'oggetto. Si consideri il seguente esempio:

    $a = {};
    $b = $a;
    bless $a, BLABLA;
    print "\$b is a ", ref($b), "\n";

Questo mette in relazione $b come se fosse un BLABLA, così facendo ovviamente bless() ha operato sull'oggetto e non sul riferimento.

Una Classe è Semplicemente un Package

Diversamente dal C++, Perl non fornisce una sintassi speciale per la definizione delle classi. Si usa un package come una classe mettendo le definizioni dei metodi dentro la classe.

C'è un array speciale all'interno di ciascun package chiamato @ISA, il quale dice dove altro cercare un metodo se non lo si riesce a trovare nel package corrente. Questo è il modo in cui Perl implementa l'ereditarietà. Ciascun elemento dell'array @ISA è solamente il nome di un altro package che in realtà è un package formante una classe. Le classi vengono cercate (con modalità depth first [ricerca in profondità, NdR]) per i metodi mancanti nell'ordine in cui ricorrono in @ISA. Le classi accessibili attraverso @ISA sono conosciute come classi base della classe corrente.

Tutte le classi ereditano implicitamente dalla classe UNIVERSAL come loro ultima classe base. Alcuni metodi comunemente utilizzati sono automaticamente forniti nella classe UNIVERSAL; per maggiori dettagli si consulti Metodi di Default di UNIVERSAL.

Se nella classe base viene trovato un metodo mancante, per ragioni di efficienza viene posto in cache nella classe corrente. Cambiare @ISA o definire nuove subroutine invalida la cache e costringe Perl ad una nuova ricerca.

Se né la classe corrente, le sue classi base, né la classe UNIVERSAL contengono il metodo richiesto, queste tre posizioni vengono ricontrollate, questa volta cercando un metodo chiamato AUTOLOAD(). Se AUTOLOAD viene trovato, questo metodo viene chiamato in vece del metodo mancante, impostando la variabile di package globale $AUTOLOAD al nome qualificato del metodo destinato ad essere chiamato.

Se nulla di tutto ciò funziona, Perl finalmente lascia perdere e protesta.

Se si vuole interrompere la catena di ereditarietà di AUTOLOAD si usi semplicemente una sub vuota

        sub AUTOLOAD;

e la chiamata originaria fallirà [die, NdT] lamentandosi di non aver trovato la sub che cercava.

Le classi Perl ereditano solamente i metodi. L'ereditarietà dei dati viene lasciata alla classe stessa. Questo in Perl non è un problema, dato che la maggior parte delle classi modellano gli attributi dei loro oggetti utilizzando un hash anonimo, che viene utilizzato come un piccolo namespace locale, al fine di essere spartito dalle varie classi che potrebbero voler far qualcosa con l'oggetto. Il solo problema con tutto ciò, è che non si è per certo sicuri di non stare utilizzando un pezzo di hash che non sia già stato utilizzato. Una soluzione ragionevole è anteporre il nome di chiave nell'hash con il nome del package.

    sub bump {
        my $self = shift;
        $self->{ __PACKAGE__ . ".count"}++;
    }

Un Metodo è Semplicemente una Subroutine

Diversamente dal C++, Perl non fornisce una sintassi speciale per la definizione dei metodi. (Sebbene esso fornisca una piccola sintassi per l'invocazione dei metodi. La si vedrà dopo). Un metodo si aspetta che il suo primo argomento sia un oggetto (riferimento) oppure un package (stringa) sul quale sia stato invocato. Ci sono due strade per chiamare i metodi, che chiameremo ``metodi classe'' e ``metodi istanza''.

Un metodo classe si aspetta il nome di una classe come suo primo argomento. Esso fornisce funzionalità per la classe nel suo insieme, non per i singoli oggetti appartenenti alla classe. I costruttori sono spesso metodi classe, ma per delle alternative si consultino perltoot e perltooc. Molti metodi classe ignorano semplicemente il loro primo argomento, perché conoscono già in quale package si trovano e non si curano del package attraverso il quale sono stati invocati. (Questi non sono necessariamente gli stessi, perché i metodi classe seguono l'albero di ereditarietà proprio come un'istanza ordinaria di un metodo). Un altro tipico utilizzo dei metodi classe è cercare un oggetto attraverso il nome:

    sub find {
        my ($classe, $nome) = @_;
        $tabellaoggetti{$nome};
    }

Un metodo di istanza si aspetta un riferimento ad un oggetto come suo primo argomento. Tipicamente esso trasferisce il primo argomento in una variabile ``self'' o ``this'', e dopo la utilizza come un normale riferimento.

    sub display {
        my $self = shift;
        my @chiavi = @_ ? @_ : sort keys %$self;
        foreach $chiave (@chiavi) {
            print "\t$chiave => $self->{$chiave}\n";
        }
    }

Invocazione del Metodo >>

Per varie ragioni, storiche e non, Perl offre due modi equivalenti per scrivere una chiamata ad un metodo. Il modo più semplice e comune è quello di utilizzare la notazione con la freccia:

    my $fred = Creatura->trova("Fred");
    $fred->visualizza("Altezza", "Peso");

Si dovrebvbe avere già familiarità con l'utilizzo dell'operatore -> con i riferimenti. Infatti poiché $fred qui sopra è un riferimento ad un oggetto, si potrebbe pensare alla chiamata al metodo semplicemente come ad un'altra forma di dereferenziazione.

Qualsiasi cosa sia sulla sinistra della freccia, un riferimento oppure un nome di una classe, viene passato al metodo come suo primo argomento. Il codice qui sopra è per lo più equivalente a:

    my $fred = Creatura::trova("Creatura", "Fred");
    Creatura::visualizza($fred, "Altezza", "Peso");

Come fa a sapere Perl in quale package si trova la subroutine? Osservando il lato sinistro della freccia, che deve essere o un nome di package o un riferimento ad un oggetto, cioè qualcosa che è stato sottoposto al bless con un package. In entrambi i casi, questo è il package in cui Perl inizia a cercare. Se tale package non ha subroutine con quel nome, Perl inizia a cercarle in tutte le classi di base di quel package, e così via.

Se è necessario, è possibile forzare Perl ad iniziare la ricerca in qualche altro package:

    my $barney = MiaCreatura->Creatura::trova("Barney");
    $barney->Creatura::visualizza("Altezza", "Peso");

Qui MiaCreatura è presumibilmente una sottoclasse di Creatura che definisce una sua versione di trova() e visualizza(). Non è stato specificato cosa questi metodi facciano, ma ciò non ha importanza visto che si è forzato Perl a cominciare la ricerca delle subroutines in Creatura.

Come caso particolare di quello precedente, si può utilizzare la pseudo-classe SUPER per dire a Perl di ricercare il metodo nei package presenti nella lista @ISA della classe corrente.

    package MiaCreatura;
    use base 'Creatura';    # imposta @MiaCreatura::ISA = ('Creatura');
    sub visualizza { 
        my ($self, @args) = @_;
        $self->SUPER::visualizza("Nome", @args);
    }

È importante notare che SUPER si riferisce alla/alle superclasse/i del package corrente e non alla/alle superclasse/i dell'oggetto. Inoltre la pseudo-classe SUPER può essere utilizzata solo come modificatrice del nome di un metodo, ma non in uno qualsiasi degli altri modi con i quali i nomi delle classi possono venire utilizzati, ad esempio:

    qualcosa->SUPER::metodo(...);       # OK
    SUPER::metodo(...);                 # SBAGLIATO
    SUPER->metodo(...);                 # SBAGLIATO

Invece del nome di una classe o del riferimento ad un oggetto, è anche possibile utilizzare qualsiasi espressione che restituisca ambedue le parti dal lato sinistro della freccia. Dunque, la seguente istruzione è valida:

    Creatura->trova("Fred")->visualizza("Altezza", "Peso");

ed anche la seguente:

    my $fred = (reverse "arutaerC")->trova(reverse "derF");

La parte destra della freccia è in genere il nome del metodo, ma può anche essere usata una semplice variabile scalare che contenga o il nome del motodo o un riferimento a subroutine.

Sintassi ad Oggetti Indiretti

L'altra strada per invocare un metodo è quella di utilizzare la notazione detta ``indirect object'' [``oggetto indiretto'', NdR]. Questa sintassi era disponibile in Perl 4 prima che fossero introdotti gli oggetti, ed è ancora utilizzata con i filehandle come questo:

   print STDERR "aiuto!!!\n";

La stessa sintassi può esser utilizzata per chiamare sia un oggetto che un metodo di una classe

   my $fred = trova Creatura "Fred";
   visualizza $fred "Altezza", "Peso";

Si noti che non c'è la virgola tra l'oggetto (o il nome della classe) e i parametri. È in questo modo che Perl può riconoscere che si desiera una chiamata indiretta al metodo piuttosto che una normale invocazione di subroutine.

Ma che cosa accade se non ci sono argomenti? In questo caso, Perl deve indovinare quello che si desidera. Ancora peggio, deve tentare questa supposizione a tempo di compilazione. Di solito Perl ci azzecca, ma quando non lo fa, si ottiene una chiamata di funzione scritta come un metodo, o viceversa. Ciò può introdurre dei bug piuttosto difficili da scovare.

Ad esempio se c'è già una funzione new nello scope, una chiamata al metodo new con la notazione indiretta (come sono soliti fare i programmatori C++) può essere erroneamente interpretata come una chiamata di subroutine. Si finirebbe per chiamare la new del package corrente come una subroutine, anziché il metodo della classe desiderato. Il compilatore cerca di imbrogliare ricordandosi le bareword require, ma il dispiacere per la confusione non vale proprio gli anni di debugging spesi a scovare un bug così insidioso.

C'è un altro problema con questa sintassi: l'oggetto indiretto è limitato ad un nome, ad una variabile scalare, o ad un blocco, visto che, altrimenti, sarebbe costretto a fare troppe previsioni di ricerca, così come qualsiasi altro dereferenziamento postfisso nel linguaggio. (Queste sono le stesse bizarre regole che si usano per i filehandle in funzioni come print e printf). Ciò può indurre ad orribili problemi di confusione nella precedenza, proprio come nelle prossime due linee:

    sposta $ogg->{CAMPO};                 # probabilmente erroneo!
    sposta $ary[$i];                      # probabilmente erroneo!

Delle quali sorprendentemente viene fatta un'analisi sintattica che porta a:

    $ogg->sposta->{CAMPO};                # Bene, all'occhio qui
    $ary->sposta([$i]);                   # Non ci si aspettava questo, eh?

Piuttosto che quello che ci si sarebbe potuto aspettare:

    $obj->{CAMPO}->sposta();              # Si dovrebbe essere cosi` fortunati.
    $ary[$i]->sposta;                     # Si`, certo.

Per ottenere un comportamente corretto con la sintassi ad oggetti indiretti, si dovrebbe utilizzare un blocco intorno all'oggetto indiretto:

    sposta {$ogg->{CAMPO}};
    sposta {$ary[$i]};

Addirittura, dunque, si potrebbe avere ancora lo stesso potenziale problema se ci fosse una funzione chiamata sposta nel package corrente. La notazione -> non soffre di queste inquietanti ambiguità, quindi si raccomanda di usare esclusivamente tale notazione. Tuttavia, si potrebbe ancora essere costretti a leggere del codice che utilizza la notazione ad oggetti indiretti, quindi è importante familiarizzare con essa.

I Metodi di Default di UNIVERSAL

Il package UNIVERSAL contiene automaticamente i seguenti metodi, che sono ereditati da tutte le altre classi:

isa(CLASSE)
isa restituisce true [``vero'', NdT] se il suo oggetto è stato sottoposto a bless in CLASSE o una sua sottoclasse.

È anche possibile chiamare UNIVERSAL::isa come una subroutine con due argomenti. Naturalmente questo farà fare la cosa sbagliata se in una classe qualcuno ha ridefinito il metodo isa, dunque non va fatto.

Se è necessario determinare se è valido utilizzare il metodo isa su una variabile, si utilizzi la funzione blessed da the Scalar::Util manpage:

    if (blessed($ref) && $ref->isa( 'UnaTal::Classe')) {
        # ...
    }

blessed restituisce il nome del package nel quale l'argomento è stato sottoposto a bless, oppure undef.

can(METODO)
can fa un controllo per verificare se il suo oggetto abbia un metodo chiamato METODO, se è così, allora viene restituito un riferimento alla subroutine, altrimenti viene restituito undef.

UNIVERSAL::can può anche essere invocata come una subroutine con due argomenti. Essa restituisce sempre undef se il suo primo argomento non è un oggetto o il nome di una classe. Inoltre, anche qui vengono applicati direttamente gli stessi avvisi come nel caso della chiamata di UNIVERSAL::isa.

VERSION( [MINIMO] )
VERSION restituisce il numero di versione della classe (package). Se viene fornito l'argomento MINIMO allora controllerà che la versione corrente (come definita dalla variabile $VERSION nel package dato) non sia minore di MINIMO; se così non fosse, terminerà con un die. Questo metodo viene di norma chiamato come un metodo di una classe. Questo metodo viene chiamato automaticamente dalla forma VERSION di use.
    use A 1.2 qw(alcune subroutine importate);
    # implica:
    A->VERSION(1.2);

NOTA: can utilizza direttamente il codice interno di Perl per fare il recupero del metodo, e isa usa un modo molto simile ed una strategia che prevede l'utilizzo di cache. Ciò può causare strani effetti se il codice Perl cambia dinamicamente @ISA in qualche package.

È possibile aggiungere altri metodi alla classe UNIVERSAL attraverso Perl o codice XS. Non c'è bisogno di use UNIVERSAL per rendere disponibili al vostro programma questi metodi (e non si deve farlo).

Distruttori

Quando viene tolto l'ultimo riferimento ad un oggetto, l'oggetto viene automaticamente distrutto. (Questo potrebbe accadere anche dopo la chiamata alla funzione exit, se sono stati salvati dei riferimenti in variabili globali). Se si desidera avere il controllo di ciò che accade appena poco prima che l'oggetto venga liberato, allora nella classe si potrebbe definire un metodo DESTROY. Esso sarà chiamato automaticamente al momento opportuno, e si potrebbero fare le ulteriori pulizie di cui si ha bisogno. Perl passa [al metodo DESTROY, NdT] un riferimento all'oggetto che sta per esser distrutto, come primo (ed unico) argomento. Si faccia attenzione che il riferimento sia un valore read-only [``accessibile in sola lettura'', NdT], e che non possa essere modificato manipolando $_[0] all'interno del distruttore. L'oggetto stesso (cioè la ``roba''' a cui il riferimento punta, cioè ${$_[0]}, @{$_[0]}, %{$_[0]} ecc.) non ha di questi vincoli.

Dato che i metodi DESTROY possono essere chiamati in momenti non prevedibili a priori, è importante che si localizzino tutte le variabili globali che il metodo può aggiornare. In particolare, si localizzi $@ se si utilizza eval {} e si localizzi $? se si utilizzano system o i backtick [``gli apici inversi ` ` che vengono utilizzati per l'esecuzione di un comando esterno'', NdT]

Se si provvede a rifare il bless del riferimento prima che il distruttore termini l'esecuzione, Perl chiamerà nuovamente il metodo DESTROY per l'oggetto risottoposto a bless dopo l'uscita dal metodo DESTROY. Questo può essere utilizzato per delegare in modo pulito la distruzione di oggetti, o per assicurarsi che vengano chiamati i distruttori desiderati nelle classi base. Chiamare esplicitamente DESTROY è possibile, ma di solito non se ne ha bisogno.

Non si confonda la discussione precedente con quella su come siano distrutti gli oggetti CONTENUTI nell'oggetto corrente. Tali oggetti saranno rilasciati e distrutti automaticamente quando l'oggetto corrente viene rilasciato, a condizione che non esistano altrove altri riferimenti ad essi.

Sommario

Questo è tutto ciò che c'è da dire. Ora ciò di cui si ha bisogno è andare a comprare un libro sulla metodologia di progettazione orientata agli oggetti, e sbatterci la fronte per i prossimi sei mesi o giù di lì.

Garbage Collection a Due Fasi

Per la maggior parte degli scopi, Perl utilizza un semplice e veloce sistema di garbage collection basato su riferimenti. Questo significa che c'è un ulteriore dereferenziamento che resta in piedi ad un qualche livello, così se i'eseguibile Perl non è stato compilato utilizzando il flag -O del compilatore C, le performance ne soffriranno. Se Perl non è stato compilato con cc -O, allora con tutta probabilità ciò non avrà importanza.

Una faccenda più seria è che la memoria non raggiungibile con un contatore di riferimenti non a zero, di norma non verrà rilasciata. Pertanto, questa è una cattiva idea:

    {
        my $a;
        $a = \$a;
    }

Anche se si pensa che $a dovrebbe sparire, non può. Quando si costruiscono strutture dati ricorsive, si dovrà rompere l'auto-referenzialità a mano, esplicitamente, a meno che non si voglia sprecare memoria. Per esempio, ecco un nodo che si auto-referenzia come si può utilizzare in una sofisticata struttura ad albero:

    sub nuovo_nodo {
        my $classe = shift;
        my $nodo  = {};
        $nodo->{SINISTRA} = $node->{DESTRA} = $nodo;
        $nodo->{DATO} = [ @_ ];
        return bless $nodo => $classe;
    }

Se si creano nodi come questi, essi (al momento) non spariranno a meno che non si interrompa il loro auto riferimento. (In altre parole, questo non dovrebbe essere interpretato come una peculiarità, e non si dovrebbe farne affidamento).

Quasi.

Quando un thread dell'interprete alla fine termina (di solito quando il programma conclude l'esecuzione), allora viene eseguita una tipologia di garbage collection mark-and-sweep [``segna e pulisci'' NdT] un po' costosa ma completa, e tutto ciò che è stato allocato da quel thread viene distrutto. Ciò è essenziale per supportare un linguaggio multithread come Perl. Per esempio, questo programma mostra la garbage collection a due fasi di Perl:

    #!/usr/bin/perl
    package Ingegnoso;
    sub new {
        my $test;
        $test = \$test;
        warn "CREAZIONE DI " . \$test;
        return bless \$test;
    }
    sub DESTROY {
        my $self = shift;
        warn "DISTRUZIONE DI $self";
    }
    package main;
    warn "avvio del programma";
    {
        my $a = Ingegnoso->new;
        my $b = Ingegnoso->new;
        $$a = 0;  # rompe l'autoreferenzialita`
        warn "sto lasciando il blocco";
    }
    warn "sono appena uscito dal blocco";
    warn "e` tempo di morire...";
    exit;

Se eseguiamo lo script come /foo/test, viene prodotto il seguente output:

    avvio del programma at /foo/test line 18.
    CREAZIONE DI SCALAR(0x8e5b8) at /foo/test line 7.
    CREAZIONE DI SCALAR(0x8e57c) at /foo/test line 7.
    sto lasciando il blocco at /foo/test line 23.
    DISTRUZIONE DI Ingegnoso=SCALAR(0x8e5b8) at /foo/test line 13.
    sono appena uscito dal blocco at /foo/test line 26.
    e` tempo di morire... at /foo/test line 27.
    DISTRUZIONE DI Ingegnoso=SCALAR(0x8e57c) during global destruction. [durante la distruzione globale, NdR]

Notate la riga che parla di ``global destruction''? Quello è il thread del garbage collection che sta raggiungendo l'irraggiungibile.

Gli oggetti sono sempre distrutti, anche quando i riferimenti non lo sono. Gli oggetti sono distrutti in un passaggio separato, prima dei riferimenti comuni, proprio per prevenire che il distruttore degli oggetti utilizzi dei riferimenti che sono stati a loro volta distrutti. I riferimenti comuni vengono sottoposti al garbage-collector se il ``destruct level'' [``livello di distruzione, NdR] è maggiore di 0. È possibile esaminare i livelli più elevati di ''global destruction`` andando ad impostare la variabile d'ambiente PERL_DESTRUCT_LEVEL, con l'assunzione che sia stato abilitato -DDEBUGGING al momento della compilazione di Perl. Per maggiori informazioni si veda perlhack/PERL_DESTRUCT_LEVEL.

In futuro sarà implementata una strategia di garbage collection più completa.

Nel frattempo, la soluzione migliore è quella di creare delle classi contenitore non ricorsive che mantengano un puntatore alla struttura dati auto referenziale. Definite un metodo DESTROY per gli oggetti della classe contenitore che vada manualmente a rompere le circolarità nella struttura auto referenziale.


SI VEDA ANCHE

Si possono tovare dei tutorial più semplici sulla programmazione orientata agli oggetti in Perl in perltoot, perlboot e perltooc. Per altri trucchi, trappole e suggerimenti sugli oggetti si dovrebbe dare una controllata a perlbot, così come perlmodlib per alcune linee guida stilistiche sulla costruzione sia di moduli che di classi.


TRADUZIONE

Versione

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

   perl -MPOD2::IT -e print_pod perlobj

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

Traduttore

Traduzione a cura di Daniele Ludovici.

Revisore

Revisione a cura di dree, dada.


Mon Jun 11 22:02:17 2012