Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
14 febbraio 2011
1 Sintassi
1
altre. Inoltre, si aggiunge la metavariabile SG che contiene le signature dei
metodi.
2 Relazione di sottotipo
2
CT(C) = class C extends D implements I {Tf; K M} m is not dened in M
mtype(m,C) = mtype(m,D)
Si noti che non può vericarsi il caso in cui un metodo m non sia denito
nella signature della classe ma si trovi nelle signature delle interfacce che essa
implementa: infatti, ogni classe deve implementare tutti i metodi delle sue
interfacce. Inoltre, non è necessario fornire una regola per mtype di metodi
non presenti nell'interfaccia ma deniti in un suo sopratipo, dal momento
che la denizione di insieme delle signature comprende anche le signature
denite nelle soprainterfacce.
Per la funzione mbody l'aggiunta delle interfacce non modica signicati-
vamente le regole: l'unica dierenza infatti è di carattere sintattico. Anche
per il predicato di overriding l'unica dierenza consiste nell'includere nella
denizione la categoria sintattica T che raccoglie le interfacce e le classi.
3
Γ ` t0 :T0 mtype(m,T0 ) = R → T Γ ` t:T T <: R
Γ ` t0 .m(t):T
elds(C)=R f Γ ` t:T T <: R
Γ ` new C(t):C
Γ ` t0 :R R<:T
Γ ` (T)t0 :T
Γ ` t0 :R T<:R T 6= R
Γ ` (T)t0 :T
Γ ` t0 :R T ≮:R R ≮:T stupid warning
Γ ` (T)t0 :T
Il sistema di tipo viene adeguato modicando le regole che deniscono la
correttezza dei metodi e delle dichiarazioni delle classi. In particolare, la
correttezza delle classi ha come ulteriore ipotesi la correttezza delle signature
dei metodi dichiarati nelle interfacce, e la presenza dell'implementazione di
tali metodi nel corpo della classe.
x : T, this:C ` t0 : R0 R0 <: T0
CT(C) = class C extends D implements I{Tf, K M} override(m, D, T → T0 )
T0 m(T x) {return t0 ;} OK in C
K = C(R g, T f ) {super(g);this.f = f;}
elds(D) = R g M OK in C Sig(I) is well formed C OK-IMPL I
class C extends D implements I{T f; K M} OK
La correttezza di un'interfaccia dipende invece solo dalla well formedness
delle signature dei metodi che dichiara e che eredita:
Sig(I) is well formed
Interface I extends I {SG} OK
4
Figura 1: Esempio di relazione di sottotipo tra interfacce
2, join(I3 ,I4 ) non è denito, dal momento che non c'è un minimo sopratipo
comune.
Java risolve il problema tipando staticamente il condizionale con un tipo
join che sostanzialmente è l'intersezione tra i minimi sopratipi delle classi o
interfacce coinvolte. Considerando l'esempio in gura 2, per Java il tipo di
b?(I3 )T:(I4 )R sarebbe l'insieme delle signature comuni alle interfacce I1 e
I2 .
Formalmente, deniamo un operatore di intersezione nel seguente modo:
CT(I1 ) = I1 implements I1 {...}, CT(I2 ) = I2 implements I2 {...}
I1 ∩ I2 = {I : I ∈ I1 ∧ I ∈ I2 }
Questo operatore restituisce un insieme che contiene le interfacce estese da
entrambi gli argomenti. La regola di typing per le espressioni condizionali in
Java diventa quindi:
Γ ` e:boolean, Γ ` A:I1 , Γ ` B:I2
Γ ` (e?A:B) : I1 ∩ I2
5
In pratica, l'espressione assume un nuovo tipo che contiene l'unione dei meto-
di presenti nelle interfacce comuni. Tale regola di typing può essere vericata
col seguente esempio:
1 public interface I1 {
2 public String m1 ();
3 }
4
5 public interface I2 {
6 public String m2 ();
7 }
8
9 public interface I3 extends I2 , I1 {
10 public String m ();
11 public String m3 ();
12 }
13
14 public interface I4 extends I2 , I1 {
15 public String m ();
16 public String m4 ();
17 }
18
19 public class A implements I3 {
20 public String m (){ return "A" ; }
21 public String m1 (){ return "A "; }
22 public String m2 (){ return "A "; }
23 public String m3 (){ return "A "; }
24 }
25
26 public class B implements I4 {
27 public String m (){ return "B" ; }
28 public String m1 (){ return "B "; }
29 public String m2 (){ return "B "; }
30 public String m4 (){ return "B "; }
31 }
Con tale struttura di classi (v. gura 2) l'esecuzione del seguente programma
non segnala errori statici:
6
1 public class Main {
2 public static void main ( String args []){
3 ( true ? new A (): new B ()). m1 ();
4 ( false ? new A (): new B ()). m2 ();
5 }
6 }
In questo caso, ad esempio, il tipo che Java crea per tipare l'espressione
condizionale è Object&I2&I1. Si noti che, sebbene sia in I3 che in I4 è
presente il metodo m con la medesima signature, esso non può essere invocato
sulle espressioni condizionali di cui sopra perché di fatto tale metodo non è
lo stesso nelle due interfacce. Si noti anche che in mancanza di interfacce
comuni i metodi disponibili per l'espressione condizionale sono soltanto quelli
di Object.