11.06.2013 Views

Polimorfismo per Sottotipo verso la programmazione orientata agli ...

Polimorfismo per Sottotipo verso la programmazione orientata agli ...

Polimorfismo per Sottotipo verso la programmazione orientata agli ...

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Polimorfismo</strong> <strong>per</strong> <strong>Sottotipo</strong><br />

<strong>verso</strong> <strong>la</strong> <strong>programmazione</strong> <strong>orientata</strong><br />

<strong>agli</strong> oggetti<br />

Motivazioni<br />

La rego<strong>la</strong> di typing (T-App) <strong>per</strong> l’applicazione funzionale è molto<br />

restrittiva: <strong>per</strong> avere un’applicazione ben tipata è necessario che<br />

l’argomento abbia esattamente il tipo richiesto dal<strong>la</strong> funzione!<br />

Ad es., <strong>la</strong> funzione λx:{a:Nat}. x.a<br />

non è applicabile ad un record r:{a:Nat, b:T}<br />

Eppure l’applicazione potrebbe essere possibile; si chiede solo che<br />

l’argomento abbia un campo a:Nat da selezionare....<br />

il record r ha questo requisito....<br />

....ha anche altro, che possiamo ignorare!<br />

1<br />

2<br />

1


Idea di base<br />

Intuizione: alcuni tipi sono più informativi di altri, dunque possono essere<br />

utilizzati anche dove si richiede meno informazione !<br />

• S


Subtyping sui tipi record<br />

• (<strong>per</strong>mutazione)<br />

<strong>Sottotipo</strong> sui tipi record<br />

{l i:T i} è una <strong>per</strong>mutazione di {l k:T k} {l i:T i}


Lambda Calcolo con Subtyping<br />

Se estendiamo il “<strong>la</strong>mbda calcolo con tipi semplici e<br />

record” con il subtyping<br />

La decidibilità del typing?<br />

si mantiene <strong>la</strong> type safety<br />

Più problematica da dimostrare <strong>per</strong>chè le regole non sono<br />

guidate dal<strong>la</strong> sintassi<br />

• transitività del subtyping<br />

• (regole di typing) T-SUB<br />

Subtyping in versione Algoritmica<br />

•Elimino <strong>la</strong> transitività dal<strong>la</strong> definizione del subtyping<br />

•La rego<strong>la</strong> di aplicazione funzionale diventa:<br />

Γ|- t:R→S Γ|- s:U U


Verso i linguaggi orientati <strong>agli</strong> oggetti<br />

• Il sistema di tipi di questi linguaggi è caratterizzato<br />

dal polimorfismo <strong>per</strong> sottotipo<br />

• Il tipo di un oggetto è l’insieme dei nomi-tipi delle<br />

sue o<strong>per</strong>azioni : interfaccia, tipo = c<strong>la</strong>sse dell’oggetto<br />

• c<strong>la</strong>sse derivata sottotipo<br />

<strong>la</strong> re<strong>la</strong>zione di sottipo è implicata dal<strong>la</strong> derivazione di<br />

c<strong>la</strong>sse definita dal programmatore : subtyping nominale<br />

invece che strutturale (<strong>la</strong> dimostrazione di re<strong>la</strong>zioni di<br />

sottotipo diventa triviale)<br />

Featherweight Java<br />

Un “core-<strong>la</strong>nguage object oriented”<br />

basato su Java<br />

9<br />

10<br />

5


Cosa c’è in FJ<br />

Scopo: Scopo astrarre i meccanismi fondamentali di Java <strong>per</strong> definire<br />

typing e semantica e provare type-safety in modo semplice.<br />

Vantaggio: Vantaggio <strong>per</strong> ogni altra caratteristica aggiuntiva, si studia<br />

l’estensione di FJ con questa caratteristica e si estende <strong>la</strong> prova di<br />

type-safety in modo ancora...semplice.<br />

Meccanismi fondamentali<br />

Termini: oggetti, creazione di oggetti, invocazioni di metodi e<br />

selezione di campi, cast.<br />

Dichiarazioni: c<strong>la</strong>ssi, ereditarietà, riscrittura di metodi e<br />

binding dinamico.<br />

Cosa non c’è.....<br />

Sono volontariamente omessi tutti quegli aspetti che renderebbero <strong>la</strong> prova di<br />

“type-safety” solo più lunga, senza introdurre elementi significativi<br />

(è comunque un frammento computazionalmente completo)<br />

Mancano (rispetto a full Java)<br />

-parte im<strong>per</strong>ativa: assegnamento e referenze<br />

-controllo dell’accesso : tutto è pubblico<br />

-eccezioni<br />

-chiamate al su<strong>per</strong> (tranne che nel costruttore)<br />

-c<strong>la</strong>ssi astratte (Interface) – inner c<strong>la</strong>ssi –<br />

-tipi di base (int, bool,...) (anche se li useremo talvolta in esempi)<br />

12<br />

11<br />

6


Un primo sguardo informale<br />

Un programma FJ è formato da<br />

Parte Dichiarativa<br />

termine (main)<br />

ESEMPIO: Parte Dichiarativa D<br />

c<strong>la</strong>ss A extends Object { A() { su<strong>per</strong>(); } }<br />

c<strong>la</strong>ss B extends Object { B() { su<strong>per</strong>(); } }<br />

c<strong>la</strong>ss Pair extends Object {<br />

Object fst; Object snd;<br />

Pair(Object fst, Object snd)<br />

{ su<strong>per</strong>(); this.fst=fst; this.snd=snd; }<br />

Pair setfst(Object newfst)<br />

{ return new Pair(newfst, this.snd); }<br />

13<br />

14<br />

7


D<br />

ESEMPIO: D + Main<br />

Lucido precedente<br />

new Pair (new A( ), new B( ) ).setfst (new B( ) )<br />

Semantica<br />

Come risultato finale ci attendiamo :<br />

new Pair (new B( ), new B( ) )<br />

Espressione da valutare nel<br />

contesto delle dichiarazioni<br />

FJ Sintassi : Termini e Valori<br />

t ::= termini<br />

x variabile<br />

t.f selezione campo<br />

t.m(t ) invocazione metodo<br />

new C(t ) creazione oggetto<br />

(C) t cast di tipo<br />

v ::= valori<br />

new C(v) creazione oggetto<br />

Dove t sta <strong>per</strong> t 1 ,..., t n , etc.<br />

15<br />

16<br />

8


FJ Sintassi : Dichiarazioni<br />

• K ::= dichiarazione costruttore<br />

C(C f) {su<strong>per</strong>(f); this.f=f;}<br />

• M ::= dichiarazione metodo<br />

C m(C x) {return t;}<br />

• CL ::= dichiarazione c<strong>la</strong>sse<br />

• c<strong>la</strong>ss C extends C {C f; K M}<br />

dove C f sta <strong>per</strong> C 1f 1...C nf n, M sta <strong>per</strong> M 1...M n, e<br />

simili.<br />

Notare!<br />

• Si esplicita sempre <strong>la</strong> su<strong>per</strong>c<strong>la</strong>sse di una c<strong>la</strong>sse<br />

(eventualmente OBJECT che è assunta essere una c<strong>la</strong>sse<br />

vuota): i campi dichiarati dal<strong>la</strong> sottoc<strong>la</strong>sse sono aggiunti a<br />

quelli del<strong>la</strong> su<strong>per</strong>c<strong>la</strong>sse (e delle sue su<strong>per</strong>c<strong>la</strong>ssi) e devono<br />

avere nomi distinti!<br />

• L’oggetto è un new esplicito con il costruttore (e eventuali<br />

parametri), non ha un’identità (non ci sono referenze)<br />

• È sempre esplicito l’oggetto su cui si invoca il metodo,<br />

anche nel caso del this<br />

• Il costruttore ha una struttura prefissata: su<strong>per</strong>(...) e<br />

inizializzazione dei nuovi campi con i (rimanenti)<br />

parametri (in ordine).<br />

17<br />

18<br />

9


C<strong>la</strong>sse = Tipo<br />

• Quando dichiaro una c<strong>la</strong>sse A , sto<br />

introducendo <strong>la</strong> definizione di un nuovo<br />

tipo di nome A<br />

• La rappresentazione interna di questo tipo A<br />

è un tipo record<br />

><br />

• Le istanze/oggetti di tipo A avranno una<br />

rappresentazione a record corrispondente<br />

SUBTYPING Nominale<br />

• Come in Java, il sottotipo è dichiarato (sottoc<strong>la</strong>sse)<br />

• Assumiamo una c<strong>la</strong>ss table CT : funzione che associa<br />

ad ogni nome di c<strong>la</strong>sse una dichiarazione<br />

• CT(C) = c<strong>la</strong>ss C extends D {...}<br />

• C


Subtyping nominale vs. Strutturale<br />

♦Nominale: i nomi sono significativi! Da essi dipende<br />

l’insieme delle re<strong>la</strong>zioni di sottotipo valide: il compi<strong>la</strong>tore, al<br />

momento del<strong>la</strong> dichiarazione di sottoc<strong>la</strong>sse, deve solo<br />

control<strong>la</strong>re che <strong>la</strong> re<strong>la</strong>zione di sottotipo sia rispettata (ad es.<br />

non ci sono nomi di campi uguali fra quelli ereditati e quelli<br />

definiti). Il confronto fra le rappresentazioni dei tipi avviene<br />

solo una volta so<strong>la</strong>.<br />

♣Strutturale: le re<strong>la</strong>zioni di sottotipo valide dipendono dal<strong>la</strong><br />

rappresentazione dei tipi (il subtyping è definito sui tipi in<br />

base al<strong>la</strong> loro struttura); ogni volta che in una derivazione di<br />

tipo devo provare una re<strong>la</strong>zione di sottotipo, devo confrontare<br />

i tipi-record che li rappresentano<br />

Nominale vs.Strutturale: Vantaggi<br />

♦ Nominale:<br />

nomi/tipi sono utili anche a run-time (tag degli oggetti)<br />

danno gratis i tipi ricorsivi e mutuamente ricorsivi (un tipo A può<br />

riferirsi ad A nel<strong>la</strong> sua definizione, oppure A si riferisce a B che si riferisce<br />

ad A senza che abbia alcun senso domandarsi quale, fra A e B, è definito<br />

<strong>per</strong> primo)<br />

<strong>la</strong> re<strong>la</strong>zione di sottotipo è decidibile in senso triviale<br />

♣ Strutturale<br />

sono molto più eleganti ed adatti a studi teorici, in quanto ogni<br />

espressione di tipo ha in sè tutte le informazioni <strong>per</strong> ragionare sulle sue<br />

proprietà<br />

21<br />

22<br />

11


Nominale vs.Strutturale:Svantaggi<br />

♦Nominale:<br />

1) Una convenzione sui nomi ( <strong>la</strong> loro rappresentazione, le re<strong>la</strong>zioni di<br />

sottotipo dichiarate, etc..) è preliminare al<strong>la</strong> stessa o<strong>per</strong>azione di controllo<br />

che <strong>la</strong> definizione del tipo è corretta (es., che i metodi siano correttamente<br />

tipati)<br />

Per esempio, una tabel<strong>la</strong> delle c<strong>la</strong>ssi del programma è costruita come passo<br />

preliminare, quindi è parametro del typing: il controllo del<strong>la</strong> correttezza sia<br />

delle dichiarazioni che del main -correttezza rispetto ai tipi- usa le<br />

informazioni di questa tabel<strong>la</strong><br />

2) Una convenzione sui nomi riguarda un “ambiente” : es., ambienti come<br />

reti etc. sono più refrattarie a tali convenzioni globali.<br />

FJ : <strong>la</strong> tabel<strong>la</strong> CT delle c<strong>la</strong>ssi<br />

Una tabel<strong>la</strong> di c<strong>la</strong>ssi CT è una funzione da nomi di c<strong>la</strong>ssi<br />

C a dichiarazioni di c<strong>la</strong>ssi CL.<br />

Un programma è una coppia (CT, p) dove p=D t :<br />

in ciò che segue assumiamo di riferirci sempre a una fissata CT<br />

(se esaminiamo il programma p, è quel<strong>la</strong> costruita dalle<br />

dichiarazioni di p)<br />

Si assume che CT soddisfi delle condizioni di consistenza (sanity<br />

conditions):<br />

i) <strong>per</strong> ogni C che compare in CT, C appartiene al dominio di CT<br />

(tranne che <strong>per</strong> OBJECT)<br />

ii) non ci sono cicli nel<strong>la</strong> re<strong>la</strong>zione


Definizioni Ausiliarie:<br />

lookup campi<br />

• fields(Object) = Ø (Ø sequenza vuota)<br />

• CT(C) = c<strong>la</strong>ss C extends D {C f; K M}<br />

fields(D) = D g<br />

fields(C) = D g; C f<br />

fields( C ): restituisce <strong>la</strong> lista dei campi di C, ereditati e nuovi<br />

Definizioni Ausiliarie:<br />

lookup tipi metodi<br />

• CT(C) = c<strong>la</strong>ss C extends D {C f; K M}<br />

B m (B x) {return t;} ∈ M<br />

mtype(m; C) = B→B<br />

• CT(C) = c<strong>la</strong>ss C extends D {C f; K M}<br />

m is not defined in M<br />

mtype(m; C) = mtype(m; D)<br />

25<br />

26<br />

13


Definizioni Ausiliarie:<br />

lookup definizioni metodi<br />

• CT(C) = c<strong>la</strong>ss C extends D {C f; K M}<br />

B m (B x) {return t;} ∈ M<br />

mbody(m; C) = (x; t)<br />

• CT(C) = c<strong>la</strong>ss C extends D {C f; K M}<br />

m is not defined in M<br />

mbody(m; C) = mbody(m; D)<br />

Definizioni Ausiliarie:<br />

riscrittura-metodi legale<br />

mtype(m; D) = D→D 0 implica<br />

C = D and C 0 = D 0<br />

override(m, D, C →C 0)<br />

Il predicato override(m, D, C →C 0 ) restituisce vero se il metodo m: C →C 0<br />

può essere definito in una sottoc<strong>la</strong>sse di D (<strong>la</strong> riscrittura del metodo è legale<br />

solo se mantiene <strong>la</strong> setssa signatura!)<br />

27<br />

28<br />

14


Semantica O<strong>per</strong>azionale<br />

• Regole di transizione <strong>per</strong> ridurre termini<br />

a valori<br />

• Semantica call-by-value : l’invocazione di un<br />

metodo è valutata solo dopo aver ridotto a valore<br />

sia il termine che rappresenta l’oggetto<br />

d’invocazione sia i parametri attuali (i valori a cui<br />

i termini si riducono sono termini di creazioneoggetti<br />

del<strong>la</strong> forma new A(v 1...v n) )<br />

• Semantica di computazione/small step<br />

Regole di valutazione<br />

Nota. A) this è una variabile (esattamente come i parametri formali), rimpiazzata<br />

dall’oggetto di invocazione nel body del metodo; B)come in Java, un cast run-time<br />

non modifica l’oggetto, semplicemente ha successo o fallisce;<br />

C) il parametro attuale è un valore<br />

29<br />

30<br />

15


Regole di Congruenza<br />

ESEMPI: Valutazione...<br />

• Selezione campo<br />

new Pair(new A(), new B()).snd<br />

• Cast<br />

→ new B()<br />

(Pair)new Pair(new A(), new B())<br />

→ new Pair(new A(), new B())<br />

31<br />

32<br />

16


ESEMPI: Valutazione<br />

• Invocazione metodo<br />

ESEMPI: Valutazione<br />

• Selezione campi + cast<br />

Definizione. La riduzione →* è definibile come al solito: è <strong>la</strong><br />

chiusura transitiva di quel<strong>la</strong> a un passo.<br />

33<br />

34<br />

17


Nota sul binding dinamico<br />

• Sistemi con tipi nominali (es. Java): ogni oggetto run-time<br />

ha un tag con il (concretamente, un puntatore al) suo tipo<br />

attuale (nome del<strong>la</strong> c<strong>la</strong>sse con il cui costruttore l’oggetto è<br />

stato creato mediante “new”), che contiene un puntatore<br />

al<strong>la</strong> su<strong>per</strong>c<strong>la</strong>sse, etc...<br />

• Il suddetto tipo attuale , con cui l’oggetto è etichettato,<br />

viene utilizzato <strong>per</strong> informazioni sul tipo dinamico, RTTI,<br />

<strong>per</strong> <strong>la</strong> ricerca dinamica dei body dei metodi associati<br />

all’oggetto (binding dinamico), etc.<br />

• In FJ non ci sono le referenze <strong>agli</strong> oggetti, l’oggetto è<br />

direttamente un new di una c<strong>la</strong>sse; <strong>per</strong>ciò il tag run-time<br />

coincide con il tipo che è argomeno del<strong>la</strong> new.<br />

Esercizio<br />

Scrivere un programma con override di un metodo e descriverne<br />

<strong>la</strong> valutazione, evidenziando il binding dinamico <strong>per</strong> <strong>la</strong> chiamata<br />

del metodo riscritto.<br />

35<br />

36<br />

18


Sistema di Tipi<br />

Insieme di regole, guidate dal<strong>la</strong> sintassi, <strong>per</strong><br />

dimostrare asserzioni del<strong>la</strong> forma<br />

• Γ ⏐⎯ t : C t ha tipo C in Γ<br />

• .... m ... OK in C m è ben tipato in C<br />

• c<strong>la</strong>ss C......... OK<br />

<strong>la</strong> definizione del<strong>la</strong> c<strong>la</strong>sse C è ben tipata<br />

dove Γ è un insieme di assunzioni del<strong>la</strong> forma x:C.<br />

Si assume già data <strong>la</strong> tabel<strong>la</strong> CT, su cui <strong>la</strong>vorano le funzioni ausiliarie.<br />

Typing dei termini<br />

(variabili e new)<br />

37<br />

38<br />

19


Typing dei termini<br />

(selezione campi/invocazione metodi)<br />

Typing dei termini (cast)<br />

Domanda Perchè 2 regole di tipo <strong>per</strong> il cast? Perchè così è in Java.....<br />

Domanda: <strong>per</strong>chè c’è, invece, una so<strong>la</strong> rego<strong>la</strong> di valutazione, quel<strong>la</strong><br />

<strong>per</strong> Up-cast, nel<strong>la</strong> semantica o<strong>per</strong>azionale ?<br />

39<br />

40<br />

20


Nota sui cast<br />

• Typing: ci sono 3 forme possibili di cast:<br />

i) in 2 di esse, il soggetto è sottoc<strong>la</strong>sse o soprac<strong>la</strong>sse del<br />

target, quindi il tipo statico (assunto dal type checker) è<br />

quello del target<br />

ii) nel<strong>la</strong> terza forma, il target ed il tipo del soggetto non<br />

hanno alcuna re<strong>la</strong>zione di sottotipo: in tal caso vogliamo<br />

che il typechecker rifiuti come mal-tipata l’espressione,<br />

infatti così è in Java............................<br />

Ancora sui cast<br />

Valutazione: quando riduco un cast, se il tipo<br />

run-time dell’oggetto è sottotipo del target,<br />

si elimina semplicemente il Cast (dunque,<br />

basta una so<strong>la</strong> rego<strong>la</strong> di valutazione):<br />

Negli altri casi mi arresto su un termine che<br />

non è un valore!<br />

41<br />

42<br />

21


Typing dei Metodi<br />

Nota: <strong>la</strong> definizione di override è un’implicazione; dunque, se<br />

m non occorre in D , l’antecedente override(...) è trivialmente<br />

vero!<br />

Typing delle C<strong>la</strong>ssi<br />

La definizione del<strong>la</strong> c<strong>la</strong>sse C è ben tipata sse il costruttore ha <strong>la</strong> forma richiesta<br />

(chiama il su<strong>per</strong> <strong>per</strong> inizializzare i campi del<strong>la</strong> soprac<strong>la</strong>sse, poi inizializza i campi<br />

aggiuntivi di C, rispettando le concordanze di tipo dei parametri) ed ogni metodo è<br />

ben tipato in C.<br />

43<br />

44<br />

22


Riassunto del Typing<br />

• Il typing è in forma algoritmica (<strong>la</strong><br />

subsumtpion è implicita dove serve)<br />

• Usando i tipi dei termini si può decidere se i<br />

metodi sono ben tipati o non (typechecking)<br />

• Se i metodi sono ben tipati, si può decidere<br />

se <strong>la</strong> c<strong>la</strong>sse è ben tipata (ossia tutti i metodi<br />

sono ben tipati, i campi e il costruttore<br />

rispettano <strong>la</strong> forma richiesta) (typechecking)<br />

Un problema sui cast (continua)<br />

Per dimostrare <strong>la</strong> type preservation con una small-step semantics è<br />

necessario (solo formalmente), introdurre gli stupid-cast<br />

Ad esempio, siano A e B sottoc<strong>la</strong>ssi di OBJECT, ma non corre<strong>la</strong>te fra<br />

loro: si consideri il seguente termine<br />

(A) (Object) new B( )<br />

che è ben tipato <strong>per</strong> il compi<strong>la</strong>tore.<br />

Ma run-time può succedere che ...??????????????<br />

(A)(Object) new B( ) → (A) new B( ) ...............<br />

chiaramente (A) new B( ) non è tipabile con nessuna delle<br />

2 regole descritte sopra<br />

45<br />

46<br />

23


Rego<strong>la</strong> <strong>per</strong> stupid-cast<br />

Per trattare formalmente il teorema di Type-Preservation<br />

(senza passare al<strong>la</strong> big-step semantics) , estendiamo le<br />

regole di Typing con <strong>la</strong> seguente rego<strong>la</strong> (T-SCast)<br />

Γ⏐⎯ t : D not(C


Type Preservation<br />

Typechecking: Un termine con un sottotipo<br />

può essere usato in ogni contesto in cui è<br />

richiesto un tipo più grande (polimorfismo)<br />

I termini (programmi) ben tipati si<br />

mantengono ben tipati durante <strong>la</strong><br />

valutazione.<br />

Nota sui Cast<br />

Un termine FJ ben tipato che non contiene down-cast<br />

si riduce sempre a termini che non contengono nè<br />

down-cast nè stupid cast.<br />

49<br />

50<br />

25


Proprietà: Progress<br />

• GOAL (Progress)<br />

Un termine ben tipato, che non contiene<br />

down-cast, o è un valore o si può ridurre<br />

con una rego<strong>la</strong> di valutazione<br />

(ossia, un termine che ha un tipo e contiene<br />

solo up-cast non può produrre fallimento, o<br />

è gia un valore o si riduce <strong>per</strong> valutazione )<br />

Progress (prova formale)1<br />

Lemma (assenza di “campo inesistente” o di<br />

“messaggio non compreso” in programmi ben<br />

tipati)<br />

Sia t un termine ben tipato:<br />

• Se t=new C(t 1,..t n).f allora<br />

f appartiene ai fields(C)<br />

• Se t=new C(t 1,..t n).m(s 1,..s k) allora<br />

mbody(m,C) = ((x 1,..x k), t0)<br />

Prova. Triviale, <strong>per</strong> induzione sulle regole di Typing<br />

51<br />

52<br />

26


Progress (prova formale)2<br />

Si deve formalizzare il concetto di “contesto di valutazione”<br />

<strong>per</strong> esprimere “il prossimo termine da ridurre”.<br />

Un contesto di valutazione E è un buco [ ] oppure E.f,<br />

E.m(t), v.m(v,E,t), new C(v,E,t), C(E).<br />

Scriviamo E[t] <strong>per</strong> indicare il termine ottenuto rimpiazzando<br />

il buco in E con t.<br />

Così, se t->t’, possiamo scrivere<br />

t come E[r] e t’ come E[r’] , <strong>per</strong> un unico E,<br />

dove r->r’ con un passo di valutazione<br />

Progress (prova formale)3<br />

Formu<strong>la</strong>zione formale del Teorema di Progress:<br />

Sia t un termine chiuso che non può essere ridotto<br />

(forma normale); allora o t è un valore oppure è<br />

uguale a un contesto di valutazione E riempito<br />

con (C)newD(v), dove D non è sottotipo di C<br />

ossia<br />

t = E[(C)newD(v)] con D non sottotipo di C.<br />

Prova. Per banale induzione sulle regole di typing.<br />

53<br />

54<br />

27


Type Safety : tiriamo le fi<strong>la</strong><br />

Cucendo insieme i risultati ottenuti:<br />

1. Se un termine FJ è ben tipato ed eseguiamo un passo<br />

di valutazione, otteniamo un termine ben tipato<br />

(Preservation)<br />

2. Se un termine è ben tipato, allora ogni selezione di<br />

campo ed invocazione di metodo è corretta (non può<br />

produrre uno stuck) ( Lemma )<br />

3. Se arriviamo ad un termine stuck (non si può ridurre<br />

e non è un valore) allora ci siamo fermati su un Cast<br />

in cui il tipo effettivo dell’oggetto non è un sottotipo<br />

del target del Cast (Progress formale)<br />

Come volevasi dimostrare : Type Safety<br />

TYPE SAFETY<br />

Un programma corretto rispetto ai tipi<br />

senza down-cast non può fallire run-time<br />

Prova. Preservation + Progress .<br />

Ovviamente in Java sono ammessi down-cast,<br />

in questo caso l’eventuale fallimento è<br />

rappresentato dal sollevamento di<br />

opportune eccezioni run-time.<br />

55<br />

56<br />

28


Esempio<br />

Siano A e B due c<strong>la</strong>ssi in cui il metodo m è riscritto, es.:<br />

c<strong>la</strong>ss A extends Object { A() { su<strong>per</strong>(); }<br />

Bool m() { return true; } }<br />

c<strong>la</strong>ss B extends A { B() { su<strong>per</strong>(); }<br />

Bool m() { return false; }}<br />

Si consideri il termine ((A) new B()).m<br />

(1) Typing: ⏐⎯(A) new B():A ossia<br />

⏐⎯((A) new B()).m :Bool<br />

(2) Valutazione: (A)new B() → new B() <strong>per</strong>ciò<br />

((A)new B()).m → new B().m<br />

che restituisce false (binding dinamico)<br />

(3) Type Preservation : (A)new B() → new B()<br />

⏐⎯(A) new B():A , ⏐⎯new B():B dove B

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!