Sovraccarico del metodo Java + doppia spedizione

Qualcuno può spiegare in dettaglio la ragione per cui il metodo di print(Parent parent) sovraccarico print(Parent parent) viene richiamato quando si lavora con l’istanza di Child nella mia parte di codice di prova?

Qualunque particolarità dei metodi virtuali o dei metodi di sovraccarico / risoluzione in Java qui coinvolti? Qualunque riferimento diretto a Java Lang Spec? Quale termine descrive questo comportamento? Molte grazie.

 public class InheritancePlay { public static class Parent { public void doJob(Worker worker) { System.out.println("this is " + this.getClass().getName()); worker.print(this); } } public static class Child extends Parent { } public static class Worker { public void print(Parent parent) { System.out.println("Why this method resolution happens?"); } public void print(Child child) { System.out.println("This is not called"); } } public static void main(String[] args) { Child child = new Child(); Worker worker = new Worker(); child.doJob(worker); } } 

Lo stato JLS in §8.4.9 Sovraccarico :

  1. Quando viene invocato un metodo (§15.12), il numero di argomenti effettivi (e qualsiasi argomento di tipo esplicito) e i tipi di tempo di compilazione degli argomenti vengono utilizzati, in fase di compilazione, per determinare la firma del metodo che verrà richiamato ( §15.12.2).
  2. Se il metodo che deve essere invocato è un metodo di istanza, il metodo effettivo da richiamare verrà determinato in fase di esecuzione, utilizzando la ricerca del metodo dinamico (§15.12.4).

Quindi nel tuo caso:

  1. L’argomento del metodo ( this ) è di tipo Parent fase di compilazione, quindi viene invocato il metodo print(Parent) .
  2. Se la class Worker era sottoclass e la sottoclass avrebbe sovrascritto quel metodo, e l’istanza worker era di quella sottoclass, il metodo sottoposto a override sarebbe stato invocato.

La doppia spedizione non esiste in Java. Devi simularlo, ad esempio utilizzando il pattern Visitor . In questo modello, in sostanza, ciascuna sottoclass implementa un metodo di accept e chiama il visitatore come argomento, e this ha come tipo di sottoclass in fase di compilazione, quindi viene utilizzato l’overloading del metodo desiderato.

La ragione è che doJob è implementato in Parent e non sovraccaricato in Child . Passa this ai methos di print del lavoratore, perché this è del tipo Parent verrà chiamato il metodo Worker::print(Parent) .

Per avere Worker::print(Parent) chiamato devi sovraccaricare doJob in Child :

 public static class Child extends Parent { public void doJob(Worker worker) { System.out.println("from Child: this is " + this.getClass().getName()); worker.print(this); } } 

Nel codice sopra this.getClass() in Child è equivalente a Child.class .