Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    Confusione sull'overriding

    Salve a tutti, mi sono accorto di avere un pò di confusione sul concetto di overriding e di se e quando viene a fatta a tempo di compilazione.
    Faccio un esempio di quello che non mi torna:

    codice:
    class A{
        String method(A a){
            return "a";
        }}
        
        class B extends A{
            String method(A a){
                return "b";
            }
            
            String method(B b){
                return "c";
            }
        }
        
    public class Lab3_1 {
    
        public static void main(String[] args) {
            A a = new A();
            B b = new B();
            A c = new B();
            System.out.println(a.method(a));
            System.out.println(b.method(b));
            System.out.println(c.method(c));
        }
    }
    In questo caso l'output è "a c b"; Quindi nel terzo caso stampa b perchè viene scelta la classe in maniera dinamica quindi B, mentre viene scelto il metodo in maniera statica quindi A per cui viene chiamato il metodo che prende A di B quindi viene stampato b. E fin qui tutto ok.

    In questo secondo caso invece:
    codice:
    class A2 {
        public void print(int num){
            System.out.println("Ciao da A: " + num);
        }
    }
    
    class B2 extends A2{
       public void print(char c){
           System.out.println("Ciao da B: " + c);
       }
        
    }
    public class lab3_2 {
    
    
        public static void main(String[] args) {
            A2 a = new A2();
            B2 b = new B2();
            a=b;
            a.print('a');
        }
    }
    C'è un output del tipo "Ciao da B: 92". Il problema è che seguendo il ragionamento che ho fatto prima dovrebbe stampare "Ciao da A: a". Perchè in questo caso la classe viene scelta staticamente e non dinamicamente?

    È chiaro che c'è qualche mia lacuna di fondo, in ogni caso se potete darmi una mano ve ne sarei grato :-)

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Confusione sull'overriding

    Originariamente inviato da CellKurt
    C'è un output del tipo "Ciao da B: 92". Il problema è che seguendo il ragionamento che ho fatto prima dovrebbe stampare "Ciao da A: a".
    L'output che deve stampare è:
    Ciao da A: 97

    Il motivo è che print(char) di B2 è un overload (non un override) di print(int) di A2. Dal momento che il metodo lo invochi su un reference di tipo A2, il compilatore "sa" solo che dovrà invocare un print(int) sull'oggetto, che realmente è un B2. E se in B2 ci fosse un public void print(int), allora invocherebbe questo. Ma l'unico che rimane è quello in A2, visto che l'altro in B2 non centra (ripeto: è un overload).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3

    Re: Re: Confusione sull'overriding

    Originariamente inviato da andbin
    L'output che deve stampare è:
    Ciao da A: 97

    Il motivo è che print(char) di B2 è un overload (non un override) di print(int) di A2. Dal momento che il metodo lo invochi su un reference di tipo A2, il compilatore "sa" solo che dovrà invocare un print(int) sull'oggetto, che realmente è un B2. E se in B2 ci fosse un public void print(int), allora invocherebbe questo. Ma l'unico che rimane è quello in A2, visto che l'altro in B2 non centra (ripeto: è un overload).

    Suppongo che questo avviene perchè il metodo da richiamare "viene deciso" a tempo di compilazione, dove viene fatto un cast implicito sul parametro, e dato che non ci sono errori di tipo, print(int) è il metodo che si prende in considerazione. Una scelta che poi viene portata avanti a tempo di esecuzione. Ci ho preso?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Re: Re: Confusione sull'overriding

    Originariamente inviato da CellKurt
    Suppongo che questo avviene perchè il metodo da richiamare "viene deciso" a tempo di compilazione, dove viene fatto un cast implicito sul parametro, e dato che non ci sono errori di tipo, print(int) è il metodo che si prende in considerazione. Una scelta che poi viene portata avanti a tempo di esecuzione. Ci ho preso?
    Le regole su overload e override sono ovviamente tante e complesse (e da Java 5 ci entrano di mezzo pure boxing/varargs e i generics), per cui se vuoi dettagli precisi ti consiglio di leggere un valido libro e/o il Java Language Specifications.

    Comunque per dirla in breve: il compilatore sceglie solo la signature (firma) del metodo da invocare basandosi:
    - sul tipo statico del reference su cui sta invocando il metodo.
    - sui tipi (e quantità nel caso dei varargs da Java 5) degli argomenti passati al metodo.

    La Virtual Machine, a runtime, invocherà la implementazione di quel metodo (con quella signature scelta dal compilatore) basandosi sull'oggetto realmente istanziato.


    Nel tuo ultimo esempio, il print lo invochi su un reference di tipo A2. L'unico metodo che il compilatore "vede" è il print(int) e siccome un char è implicitamente convertibile a int, allora la scelta del metodo ha successo. Il compilatore non "vede" il print(char) di B2.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Grazie mille, sei stato chiaro e coinciso!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.