Telemat Lab's home page


Copyrigtht © 2000 Universita' di Firenze. All rights reserved.

Free license available.

 

Moduli e Oggetti in Perl

Ereditarietà in Perl

A cura di: David Cristofani

Revisori: Prof. Franco Pirri  , Ing. Claudio Bizzarri 


Ereditarietà in Perl

HYPER HOME Indice gen. Indice prec. Indice attuale Indice succ.

Indice generale
Indice lezione attuale
Slide iniziale gruppo precedente
Slide succesiva
Testo
slide 1
Slide 1/4

Cerchiamo di capire il funzionamento dell'ereditarietà con un semplice esempio:


package Persona;

sub new
{
 my $primo_par = shift;
 my $classe = ref($primo_par) || $primo_par;
 
 my $this = {};
 
 bless ($this, $classe);

 return $this;
}

package Studente;
@ISA = qw(Persona);

package main;

$persona = Persona->new();
$studente =Studente->new();

$oggetto1 = ref($persona);
$oggetto2 = ref($studente);

print "$oggetto1\n"
print "$oggetto2\n";

Andando ad eseguire questo codice si ottiene la stampa a video di:

Persona
Studente

Con l'istruzione
$persona = Persona->new();
si invoca l'esecuzione del metodo costruttore della classe Persona, cioè di un metodo che è effettivamente implementato in tale classe.
Al contrario con l'istruzione
$studente = Studente->new();
si invoca un metodo che non è stato definito nella classe Studente.
In questo caso l'interprete del Perl controlla se nella classe Studente è stato definito l'array @ISA e, se è definito, lo consulta per vedere se esiste una classe da cui Studente eredita che può fornirgli tale metodo.
Ovviamente, nel nostro caso, l'interprete trova che il metodo new() è implementato nella classe Persona (l'unica presente in @ISA) e quindi lo esegue.

Fra poco spiegheremo come avvenga la ricerca di un metodo non definito in una classe ma prima dobbiamo chiarire un altro punto.
Abbiamo stabilito che l'invocazione del metodo new() sulla classe Persona e sulla classe Studente comporta l'esecuzione della stessa funzione, cioè la funzione new() implementata in Persona: come mai allora ci accorgiamo che $persona è un reference a un oggetto della classe Persona e che invece $studente è un reference a un oggetto della classe Studente?
La spiegazione si può trovare analizzando l'implementazione del costruttore new() e, in particolare, il modo in cui viene utilizzata al suo interno la funzione bless().

Il costruttore accetta come primo parametro o il reference ad un oggetto o il nome di una classe e memorizza nella variabile $classe il nome della classe da cui il metodo è stato invovato.
Successivamente la funzione bless() benedice il reference al coso appena creato ($this) con il nome della classe contenuto in $classe
bless ($this, $classe);
in questo modo ogni nuovo oggetto apparterrà alla classe da cui il metodo new() viene invocato.


Osservazioni

Sulla base di questo esempio si comprende che, per poter sfruttare il meccanismo dell'ereditarietà, non si deve mai vincolare un costruttore ad utilizzare il nome esplicito della classe che deve benedire.

L'esempio riportato illustra il funzionamento dell'ereditarietà singola. L'ereditarietà multipla viene trattata in modo del tutto analogo: è sufficiente che l'array @ISA contenga la lista di tutte le classi base da cui la nuova classe deve ereditare.

Slide successiva Slide precedente

 

 

 

 

Indice generale
Indice lezione attuale
Slide iniziale
Slide precedente
Slide successiva
Testo
slide 2
Slide 2/4

Ogni nuova classe eredita implicitamente i metodi messi a disposizione dalla classe UNIVERSAL tra cui:

Slide successiva Slide precedente

 

 

 

 

Indice generale
Indice lezione attuale
Slide iniziale
Slide precedente
Slide successiva
Testo
slide 3
Slide 3/4

Quando si invoca un metodo di una classe l'interprete del Perl segue la seguente sequenza di ricerca per trovare il punto in cui il metodo stesso è stato definito:

Se durante la ricerca il metodo viene trovato allora la sequenza di ricerca viene subito interrotta e il controllo viene passato a tale metodo.

Consideriamo ancora il nostro esempio e supponiamo di invocare il metodo Studente->visualizza().
In questo caso la sequenza di ricerche effettuata dall'interprete Perl sarà data da:
Studente::visualizza
Persona::visualizza
UNIVERSAL::visualizza
Studente::AUTOLOAD
Persona::AUTOLOAD
UNIVERSAL::AUTOLOAD

Slide successiva Slide precedente

 

 

 

 

Indice generale
Indice lezione attuale
Slide iniziale
Slide precedente
Testo
slide 4
Slide 4/4

Quando si definisce una classe derivata a partire da una classe base spesso si presenta la necessità di dover modificare il suo costruttore (rispetto a quello della classe base) per poter aggiungere ulteriori attributi alla nuova classe oltre a quelli ereditati.
Cerchiamo di mostrare come ciò sia possibile riprendendo il nostro esempio.
Supponiamo di avere quindi la classe base Persona caratterizzata dagli attributi nome e cognome e di voler derivare da essa la nuova classe Studente che, oltre agli attributi ereditati, possieda anche l'attributo matricola.
Questo risultato si può ottenere nel modo seguente:


package Persona;

sub new
{
 my $primo_par = shift;
 my $classe = ref($primo_par) || $primo_par;
 my ($nome, $cognome) =@_;

 my $this = {};
 $this->{'nome'} = $nome;
 $this->{'cognome'} = $cognome;

 bless($this, $classe);

 return $this;
}


package Studente;

@ISA = qw(Persona);

sub new
{
 my $primo_par = shift;
 my $classe = ref($primo_par) || $primo_par;
 my ($nome, $cognome, $matricola) = @_;

 $this = Studente->Persona::new($nome, $matricola);
 $this->{'matricola'} = $matricola;

 return $this;
}

Se analizziamo il costruttore della classe Studente possiamo osservare che:
Osservazioni

Se osserviamo più attentamente l'istruzione con cui viene invocata l'esecuzione del metodo new() della classe Persona
$this = Studente->Persona::new($nome, $cognome);
possiamo notare che ci sono due inconvenienti: La funzione new() è disponibile sia per la classe Persona che per la classe Studente e, in ognuna di queste due classi, ha un'implementazione diversa.
L'utilizzo della corretta implementazione della funzione new() viene lasciato a carico dell'interprete che può effettuare la scelta andando a controllare la classe di appartenenza dell'oggetto a cui la funzione viene applicata.
E' proprio in questo modo che il Perl realizza il concetto di polimorfismo e, per quanto affermato nella slide, la funzione new() è una funzione polimorfa.

Slide precedente


Ultimo aggiornamento 5/12/2000.

Slide iniziale


Telemat Lab's home page

HYPER HOME Indice generale Indice prec. Indice attuale Indice succ.