2011-02-23 2 views
3

J'ai quelques problèmes avec l'exemple suivant (pour être plus précis, avec une ligne spécifique). Voici le code (question suivante par la suite):Polymorphisme Java - Exemple spécifique

public class Up 
{ 
    public void cc(Up u) {System.out.println("A");} 
    public void cc(Middle m) {System.out.println("B");} 
} 

public class Middle extends Up 
{ 
    public void cc(Up u) {System.out.println("C");} 
    public void cc(Down d) {System.out.println("D");} 
} 

public class Down extends Middle 
{ 
    public void cc(Up u) {System.out.println("E");} 
    public void cc(Middle m) {System.out.println("F");} 
} 

public class Test 
{ 
    public static void main(String... args) 
    { 
     Up uu = new Up(); 
     Up pp = new Middle(); 
     Down dd = new Down(); 

     uu.cc(pp); // "A" 
     uu.cc(dd); // "B" 
     pp.cc(pp); // "C" 
     pp.cc(dd); // "B" 
     dd.cc(pp); // "E" 
     dd.cc(dd); // "D" 
    } 
} 

Maintenant uu.cc(pp); et uu.cc(dd); sont assez évidentes, car uu est une instance de Up et pp "ressemble à" un aswell Up (au moment de la compilation). La méthode la plus appropriée pour dd est cc(Middle m) car dd est une instance de Down qui hérite de Middle. Les lignes avec lesquelles j'ai le plus de problèmes sont pp.cc(dd); et dd.cc(dd). Je suis vraiment un peu confus quant à la méthode qui est choisie quand et comment ces choses sont déterminées lors de la compiliation ou à l'exécution. Je serais heureux si quelqu'un pouvait m'aider à comprendre.

Répondre

5

Fondamentalement, la méthode signature est choisie au moment de la compilation en fonction des types temps de compilation des expressions impliquées et la mise en œuvre est choisi au moment de l'exécution, en fonction de la mise en œuvre effective juste de la cible de la méthode.

Donc, au moment de la compilation, pp.cc(dd) essaie de trouver une correspondance pour Up.cc(Down). La correspondance la plus spécifique est Up.cc(Middle), donc c'est ce qui finit dans le code compilé. Maintenant, à exécution, l'implémentation de ce sera Up.cc(Middle) car Middle ne remplace pas cette signature de méthode. D'où il imprime "B".

maintenant au moment de la compilation, dd.cc(dd) essaie de trouver une correspondance pour Down.cc(Down). Il y a deux choix pertinents ici - soit Middle.cc(Down) qui correspond au paramètre exactement, ou Down.cc(Middle) qui correspond au type de cible exactement. Le compilateur préfère Middle.cc(Down). Au moment de l'exécution, encore une fois cette méthode n'a pas été remplacée dans Down, de sorte qu'il imprime "D".

Le bit pertinent de la spécification pour la résolution de surcharge est 15.12, et en particulier 15.12.2 - determining the method signature.

0

Dans pp.cc(dd); le compilateur doit choisir entre les méthodes appartenant au type de pp, Up. Le meilleur ajustement est cc(Middle m). Vous ne remplacez pas cette méthode dans Middle, donc l'exécution de la méthode Up est appelée.

Dans dd.cc(dd) le compilateur choisit entre les deux méthodes appartenant à Down, Middle ou Up depuis dd est un Down. Middle la méthode cc(Down) correspond exactement au type de dd et est choisi. Donc, à l'heure de la compilation, le choix est fait en fonction du type déclaré de la variable et de la signature de méthode la plus appropriée. Les règles de remplacement normales s'appliquent alors à l'exécution.