Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da...

24
Dispatch

Transcript of Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da...

Page 1: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Dispatch

Page 2: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Overriding vs overloading

• Notare che esistono due fasi nella selezione del metodo da invocare:

• Fase statica: risoluzione dell’overloading determina il tipo del metodo, in funzione del tipo

statico degli argomenti presenti nel messaggio

• Fase dinamica: dispatch determina il corpo del metodo, in funzione del tipo

dinamico del parametro implicito (ovvero, del destinatario del messaggio)

Page 3: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Polimorfismo – run time

• Dispatch articolato di quanto abbiamo visto …

• Metodi dispatch dinamico, con le seguenti eccezioni: metodi private, chiamate via super

• Metodi di classe (static) dispatch è sempre statico

• Campi dispatch è sempre statico, sia per variabili di istanza,

sia per variabili di classe (o static)

Continua…

Page 4: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Invocazione di metodi

• exp.m(a1,..., an) per definire precisamente l’effetto della chiamata

dobbiamo analizzare tre aspetti:

• selezione statica decide se è corretto invocare m(…) su exp, ovvero

se esiste un metodo da invocare determina il tipo del metodo da invocare

• dispatch determina il corpo del metodo da invocare

Page 5: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Selezione statica

exp.m(a1,..., an)

Due fasi:

1. Determina il tipo di exp

2. Determina la firma T m(T1,…Tn) del metodo da invocare in base al tipo degli argomenti a1,...,an

In questa fase (statica)

• tipo = tipo statico

Page 6: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Selezione Statica – Fase 1

exp.m(a1,..., an)

• Determina il tipo statico S di exp:1. exp = super:

• S è la superclasse della classe in cui l’invocazione occorre:

2. exp = this: • S è la classe in cui l’invocazione occorre

3. in tutti gli altri casi:• S è il tipo dichiarato per exp

Page 7: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Selezione statica – Fase 2

exp.m(a1,..., an) exp:S

• Determina la firma del metodo da invocare 1. calcola il tipo degli argomenti, a1:S1,.... an:Sn2. seleziona in S il metodo T m(T1,....,Tn) tale

che Si <:Ti e m() è accessibile dal contesto di chiamata

3. se S non ha un metodo m() con le caratteristiche desiderate, ripeti il passo 2 sul supertipo di S (ognuno dei supertipi di S ), finché non trovi un metodo oppure esaurisci la gerarchia.

Page 8: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Selezione statica e overloading

• L’algoritmo appena visto assume che ogni classe contenga al più una versione del metodo da invocare

• Che succede se esiste una classe contiene più di una versione?

• Che succede se una classe ed una superclasse contengono diverse versioni dello stesso metodo?

• Sono entrambi casi di overloading, e la selezione statica deve risolverlo

• Selezione statica richiede overloading resolution

Page 9: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Selezione statica – Fase 2 rivista

exp.m(a1,..., an) exp:S

• Determina la firma del metodo da invocare1. calcola il tipo degli argomenti, a1:S1,....

an:Sn

2. determina il best match T m(T1,...,Tn) per l’invocazione m(a1:S1,… an:Sn), a partire da S

• Se trovi una sola firma ok, altrimenti errore

Page 10: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Best Match

exp.m(a1:S1,..., an:Sn) exp:S

1. Determina l’insieme dei metodi applicabili

APP(S, m(S1, ..., Sn)) =

{U1.m(T11,...,T1n),...,Uk.m(Tk1,...,Tkn)}

tali che, per ogni j in [1..k] S <: Uj (quindi: esamina S ed i supertipi di S) m(Tj1, …. Tjn) è definito in Uj ed è visibile nel

punto della chiamata exp.m(a1,…,an). Si <: Tji per ogni i in [1..n]

2. Se l’insieme è vuoto fallisci

Page 11: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

3. Altrimenti, calcola l’insieme dei metodi migliori

BEST(S,m(a1:S1,…,. an:Sn))

rimuovi da APP(S, m(a1:S1, ... an:Sn)) ogni Up.m(Tp1, ..., Tpn) tale che esiste un metodo migliore, ovvero un metodo Uq.m(Tq1,...,Tqn) tale che - Uq <:Up (è definito in una superclasse più vicina a S) - Tqi <: Tpi (ha tipi degli argomenti piu vicini agli Si)

4. Se BEST(S,m(a1:S1,…,an:Sn)) contiene più di un metodo, fallisci.

Altrimenti l’unico metodo nell’insieme e` il best match per la chiamata exp.m(a1,...,an)

Best Match

Page 12: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

APP(A, m(int)) = { A.m(int) }

APP(B, m(String)) = { B.m(String) }

APP(B, m(int)) = { A.m(int) }

class A { public void m(int i) { System.out.println("A.m(int)"); }}class B extends A { public void m(String s) { System.out.println("B.m(String)"); }}class over { public static void main(String[] args) { B b = new B(); A a = new B(); a.m(1) b.m(“a string”) ; b.m(1); }}

Best Match – Esempi

// APP(A,m(int)) = {A.m(int)}// APP(B,m(String))= {B.m(String)}// APP(B,m(int)) = {A.m(int)}

Page 13: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Best Match – Esempi

APP(A, m(int)) = { A.m(int) }

APP(B, m(String)) = { B.m(String) }

APP(A, m(String)) = { }

class A { public void m(int i) { System.out.println("A.m(int)"); }}class B extends A { public void m(String s) { System.out.println("B.m(String)"); }}class over { public static void main(String[] args) { B b = new B(); A a = new B(); a.m(1) b.m(“a string”) ; a = b; a.m(“a string”); }}

// APP(A,m(int)) = {A.m(int)}// APP(B,m(String))= {B.m(String)}

// APP(A,m(string))= {}

Page 14: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Best Match – Esempiclass A {

public void m(int i) { System.out.println("A.m(int)"); }

}

class B extends A {

public void m(double f) { System.out.println("B.m"); }

}class over { public static void main(String[] args) { B b = new B(); A a = new B(); a.m(1); b.m(1.5); b.m(1); }}

// APP(A,m(int)) = {A.m(int)}// APP(B,m(double))= {B.m(double)}// APP(B,m(int)) = {A.m(int),B.m(double)}// BEST(B.m(int)) = {A.m(int),B.m(double)}

Page 15: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Best Match – Esempiclass A {

public void m(double g) { System.out.println("A.m"); }

}

class B extends A {

public void m(int i) { System.out.println("B.m"); }

}class over { public static void main(String[] args) { B b = new B(); A a = new B(); a.m(1); b.m(1.5); b.m(1); }}

// APP(A,m(int)) = {A.m(double)}// APP(B,m(double))= {A.m(double)}// APP(B,m(int)) = {A.m(double),B.m(int)}// BEST(B.m(int)) = {B.m(int)}

Page 16: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Best Match – Esempi

class A {

public void m(int i, float f) { /* just return */}

public void m(float f, int i) { /* just return */}

}

class test {

public static void main(String[] args) {

A a = new A();

a.m(1, 1);

}

// APP(A, m(int,int)) = { A.m(int,float), A.m(float,int) }

// BEST(A,m(int,int)) = { A.m(int,float), A.m(float,int) }

Page 17: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Invocazione di metodi

exp.m(a1,..., an) per definire precisamente l’effetto della chiamata dobbiamo

analizzare tre aspetti:

• selezione statica: determina la firma del metodo da invocare calcolo del best match

• dispatch dinamico: determina il corpo del metodo da invocare se il dispatch è statico esegui il corpo del metodo determinato

dalla selezione statica altrimenti esegui il corpo del metodo con il tipo determinato

dalla selezione statica che trovi a partire dal tipo dinamico di exp

Page 18: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Esempio class A {

public void m(double d){System.out.println("A.m(double)");

public void m(int i) { System.out.println(“A.m(int)"); }

}

class B extends A {

public void m(double d){System.out.print(“B.m(double)”); }

}

class over {

public static void main(String[] args) {

{ A a = new B(); a.m(1.5); }

}

// Selezione statica: BEST(A, m(double)) = { A.m(double) }

// Dispatch: B ridefinisce m(double). Quindi esegui B.m(double)

Page 19: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Esempio class A {

public void m(double d){ System.out.println("A.m(double)");

public void m(int i) { System.out.println(“A.m(int)"); }

}

class B extends A {

public void m(double d){System.out.print(“B.m(double)”); }

}

class over {

public static void main(String[] args) {

{ A a = new B(); a.m(1); }

}// Selezione statica: BEST(A, m(int)) = { A.m(int) }

// Dispatch: B non ridefinisce m(int). Quindi esegui A.m(int)

Page 20: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Esempio

class A {

public void m(double d){ System.out.println("A.m(double)");

public void m(int i) { System.out.println(“A.m(int)"); }

}

class B extends A {

public void m(double d){System.out.print(“B.m(double)”); }

}

class over {

public static void main(String[] args) {

{ B b = new B(); b.m(1); }

}// Selezione statica: BEST(A, m(int))={A.m(int),B.m(double)}

Page 21: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Metodi private : dispatch statico

• Essendo private , non sono accessibili alle sottoclassi.

• Quindi le sottoclassi non possono fare overriding di questi metodi

• Dispatch può essere deciso dal compilatore

Continua…

Page 22: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Metodi private : dispatch statico

class A { public String test() { return this.sd() + " , " + this.dd(); } private String sd(){ return "A.sd()"; } public String dd() { return "A.dd()"; }}

class B extends A { public String sd() { return "B.sd()"; } public String dd() { return "B.dd()"; }}. . . // new B().test() = “A.sd(), B.dd()”// new A().test() = “A.sd(), A.dd()”

dispatch statico: A.sd()

dispatch dinamico: risolto a run time

Page 23: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Chiamate via super: dispatch statico

class A { public String test() { return dd(); } public String dd() { return "A.dd()"; }}

class B extends A { public String dd(){ return (super.dd() + " , " + "B.dd()"); }}. . . // super.dd() invoca sempre A.dd()// new B().test() = “A.dd(), B.dd()”// new A().test() = “A.dd()”

Page 24: Dispatch. Overriding vs overloading Notare che esistono due fasi nella selezione del metodo da invocare: Fase statica: risoluzione delloverloading determina.

Campi: dispatch staticoclass C { String str = "C"; public void m() { System.out.println(str); }}class D extends C { String str = "D"; public void n() { System.out.println(str); }}

. . . D d = new D(); d.m(); // Cd.n(); // D System.out.println(d.str); // DC c = d;

c.m(); // C

((D)c).n(); // D

System.out.println(c.str); // C