|
Carissimi,
ho finito la lettura dell'Apocalisse 12 e, sobillato anche da larsen, ho
deciso di tramutare ciò che inizialmente avevo pensato come un semplice
"impressioni a caldo" in qualcosa di più corposo e articolato. Qualcosa che
vuol essere una specie di riassunto di ciò che ho capito o mi ha colpito, e un modo anche per esercitarmi nella scrittura di pseudo-code in Perl6 :-)
Prevedo quindi di integrare questo post iniziale con ulteriori commenti, man
mano che vado avanti nella digestione del corposissimo corpus Walliano.
Premessa
Come già Larry con "apocalisse", non intendo utilizzare la parola "omelia"
nella sua accezione comune, di matrice ecclesiastica, di "sermone, spiegazione delle Sacre Scritture ai fedeli" (lungi da me l'idea di salire su un qualsivoglia pulpito!), ma nell'accezione più vicina all'etimo greco
"homilìa", che sta per conversazione.
Mi piacerebbe che la conversazione non rimanesse monologo, quindi vi invito a partecipare correggendomi dove sbaglio, o aggiungendo dove tralascio, o
riportando le vostre impressioni. Avete a disposizione la possibilità di
commentare, quindi abusatene pure.
Gli oggetti nel quotidiano
Per quanto riguarda l'utilizzo "comune" di classi ed oggetti (i casi più
semplici che rappresentano poi una buona percentuale dei casi totali, il
quotidiano appunto), molto è stato fatto per rendere il più esplicito
possibile ciò che dev'essere esplicito e il più implicito possibile ciò che
dev'essere implicito.
La differenza principale sta nel fatto che un oggetto non è più
esplicitamente, nel codice, una reference (quasi sempre, una reference ad un hash) sottoposta a bless, ma un qualcosa di "opaco" allo sguardo occasionale.
Per spiegarci meglio, vediamo come può essere implementata una semplice classe in Perl6:
class Persona {
has $.nome;
has $.cognome;
has $.soprannome = $.nome;
method saluta {
say $.soprannome ~ ": ciao";
}
}
my $dada = Persona.new( nome => "Aldo", cognome => "Calpini");
$dada.soprannome = "dada";
$dada.saluta();
my $nominativo = $dada.nome ~ " " ~ $dada.cognome;
Qui vediamo all'opera le sostanziali differenze:
- attributi espliciti (non più chiavi di hash ma variabili introdotte da "has")
- metodi espliciti (non più "sub" ma "method")
- costruttore implicito ("new" non dev'essere definito)
- metodi accessori (lettura/scrittura degli attributi) impliciti
Ovviamente, è sempre possibile implementare il tutto in maniera diversa (anche implementarlo con un hash, come ai bei vecchi tempi del Perl5). E' possibile scrivere un metodo "new", o "overloadare" le funzioni per accedere agli attributi che Perl6 crea per noi.
Ciò che mi piace particolarmente, di tutta questa implementazione, è l'innata ortogonalità delle operazioni: il fatto di fornire un "new" di default, ad esempio, non deriva da qualche magia nera, ma semplicemente dal fatto che ogni classe eredita, volente o nolente, dalla classe Object, la quale implementa appunto il metodo new in questione.
Privacy
Si possono (finalmente, sospirerà qualcuno) creare attributi, e perfino
metodi, davvero "privati", nel senso che sono interni alla classe e nessuno,
neanche con i salti mortali (immagino), può utilizzarli dall'esterno.
L'identificatore che segnala la nostra richiesta di riservatezza sono i due
punti:
class Personalita {
has @.:inconscio;
method :rimozione( $self: $indesiderato ) {
push(@self.:inconscio, $indesiderato);
}
}
Nessuno potrà vedere ciò che c'è nel nostro inconscio, né tantomeno
interferire con i nostri meccanismi di rimozione :-)
Ereditarietà
Non molto da dire, se non che non si usa più @ISA, ma si danno esplicitamente dei "tratti" alla classe:
class Utente is Persona {
has $.login = $.nome;
has $.password;
has $.home = "/home/$.login";
}
class Luser is Utente is Incompetente is Seccatura; # :-)
Classi e Ruoli
Una novità (a mio avviso meravigliosa) che porterà il Perl6 per sfruttare al
meglio le potenzialità della programmazione OO è quella dei ruoli. I ruoli non sono "propriamente" classi, o meglio sono classi, ma dalle quali non è possibile costruire direttamente oggetti.
Quello che permettono di fare i ruoli, fondamentalmente, è di costruire classi complesse, o gerarchie di classi, non solo tramite il meccanismo
dell'ereditarietà ma tramite quello della "composizione".
role Programmatore is {
has @.linguaggi_conosciuti = <<nessuno>>;
method scrivi_codice($linguaggio, $righe) {
die unless @.linguaggi_conosciuti ~~ $linguaggio;
sleep($righe*10);
}
}
class Dipendente is Utente {
has $.matricola;
does Programmatore;
}
Non solo: è possibile associare dei ruoli ad oggetti già creati! Questo
permette di creare dei "mixin", una sorta di oggetti ibridi, creati secondo una classe, ma che assumono in seguito (in qualunque momento decidiamo noi) tratti di un'altra classe:
my $dada = Persona.new();
$dada does Programmatore;
push($dada.linguaggi_conosciuti, 'Perl');
Ovviamente, l'implementazione dell'operatore di match, quando applicato ad
oggetti, utilizza quindi il metodo .does (invece di .isa) che ritorna un
valore vero sia per la classe propria dell'oggetto, che per classi
ereditate, che per ruoli in qualunque modo "assegnati" ad esso:
if($dada ~~ Programmatore) {
$dada.scrivi_codice(linguaggio => 'Perl', righe => 1000);
}
Delegare, delegare, delegare
Un ulteriore meccanismo a disposizione del disegnatore di classi è quello
della "delegation", ossia il demandare ad altre classi la gestione di alcuni
metodi. L'implementazione prevede sempre e comunque un attributo che contenga il riferimento ad un oggetto della classe alla quale si intende delegare.
class Dipendente is Persona {
has Qualifica $.ruolo handles 'lavora';
}
in questa maniera
$dada.lavora(); # è in realtà $dada.ruolo.lavora();
La cosa particolarmente carina è che si possono usare anche espressioni
regolari per decidere quali metodi delegare:
class Persona {
has Schiavo $.schiavo handles (/[lava | pulisci | stira]/);
}
E abbiamo così delegato al nostro "Schiavo" tutti i lavori di casa :-)
Altro
L'Apocalisse contiene molto, molto di più, incluse modifiche al linguaggio
decise da Larry e team nel tempo trascorso dalla pubblicazione dell'ultimo
documento e che poco o nulla hanno a che fare con l'OOP. Degli argomenti
principali, quelli che mi risultano meno chiari sono:
- submetodi
- "alias" privati di classi
- in generale, tutto il meccanismo di dispatch :-)
- AUTOLOAD e i suoi nuovi amici AUTOMETH, AUTOMETHDEF, etc.
- definizione dei tipi
Mi riprometto di studiarmeli meglio per la prossima volta :-)
cheers,
Aldo
Inviato da dada alle 19:08
| Commenti (8)
|