1 / 24

Dispatch

Dispatch. 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

damisi
Télécharger la présentation

Dispatch

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Dispatch

  2. 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)

  3. 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…

  4. 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

  5. Selezione statica exp.m(a1,..., an) Due fasi: • Determina il tipo di exp • 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

  6. Selezione Statica – Fase 1 exp.m(a1,..., an) • Determina il tipo statico S di exp: • exp = super: • Sè la superclasse della classe in cui l’invocazione occorre: • exp = this: • Sè la classe in cui l’invocazione occorre • in tutti gli altri casi: • Sè il tipo dichiarato per exp

  7. Selezione statica – Fase 2 exp.m(a1,..., an)exp:S • Determina la firma del metodo da invocare • calcola il tipo degli argomenti, a1:S1,.... an:Sn • seleziona in S il metodo T m(T1,....,Tn)tale che Si<:Ti e m() è accessibile dal contesto di chiamata • 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.

  8. 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

  9. Selezione statica – Fase 2 rivista exp.m(a1,..., an)exp:S • Determina la firma del metodo da invocare • calcola il tipo degli argomenti, a1:S1,.... an:Sn • determina il best matchT m(T1,...,Tn)per l’invocazione m(a1:S1,… an:Sn), a partire da S • Se trovi una sola firma ok, altrimenti errore

  10. 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 jin[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

  11. Best Match • 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 aS) - Tqi<:Tpi (ha tipi degli argomenti piu vicini agli Si) • 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)

  12. Best Match – Esempi 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); } } APP(A, m(int)) = { A.m(int) } APP(B, m(String)) = { B.m(String) } APP(B, m(int)) = { A.m(int) } // APP(A,m(int)) = {A.m(int)} // APP(B,m(String))= {B.m(String)} // APP(B,m(int)) = {A.m(int)}

  13. Best Match – Esempi 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)) = { } // APP(A,m(int)) = {A.m(int)} // APP(B,m(String))= {B.m(String)} // APP(A,m(string))= {}

  14. Best Match – Esempi class 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)}

  15. Best Match – Esempi class 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)}

  16. 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) }

  17. 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

  18. 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 eseguiB.m(double)

  19. 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 eseguiA.m(int)

  20. 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)}

  21. 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…

  22. 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

  23. 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()”

  24. Campi: dispatch statico • class 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(); // C • d.n(); // D • System.out.println(d.str); // D • C c = d; • c.m(); // C • ((D)c).n(); // D • System.out.println(c.str);// C

More Related