Question

Je pratique pour un examen et j'ai trouvé un exemple de problème qui me perd complètement. Pour le code suivant, recherchez le résultat:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe()); 
        ((Curly)stooge1).print(new Larry()); 
        ((Larry)stooge2).print(new Moe()); 
        stooge2.print(new Curly()); 
        stooge3.print(new Curly()); 
        stooge3.print(new Moe()); 
        stooge3.print(new Larry()); 
        ((Curly)stooge3).print(new Larry()); 
        ((Curly)stooge3).print(new Curly()); 
        stooge4.print(new Curly()); 
        stooge4.print(new Moe()); 
        stooge4.print(new Larry()); 
        stooge5.print(new Curly()); 
        stooge5.print(new Larry()); 
        stooge5.print(new Moe()); 
    }
}

J'avais mes idées en tête, mais quand j'ai utilisé le java, j'ai eu quelque chose de totalement différent:

Curly 1
Curly 2
Larry 1
Larry 1
Curly 1
Curly 1
Curly 1
Curly 2
Curly 3
Curly 3
Curly 1
Curly 2
Larry 2
Larry 2
Larry 1

Les premiers sont acceptables, mais je ne comprends vraiment pas. Quelqu'un a une bonne explication à ce problème?

Merci

Était-ce utile?

La solution

Je commencerais par dessiner une image ...

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)

Ensuite, je garderais une trace des variables:

  • Larry - stooge1 - > Bouclé
  • Moe - stooge2 - > Larry
  • Moe - stooge3 - > Bouclé
  • Curly - stooge4 - > Bouclé
  • Larry - stooge5 - > Larry

  • stooge1.print (new Moe ())

    • stooge1 - > Curly appelle Curly.print (Moe)
  • ((Curly) stooge1) .print (new Larry ());

    • stooge1 - > Curly so appelle Curly.print (new Larry ())
  • ((Larry) stooge2) .print (new Moe ());

    • stooge2 - > Larry appelle alors Larry.print (new Moe ());
  • stooge2.print (new Curly ());
    Ok, c’est là que ça devient un peu plus compliqué (désolé d’en avoir arrêté un avant ici)

    • stooge2 est déclaré Moe. Ainsi, lorsque le compilateur cherche comment appeler, il appelle la méthode print (Moe). Ensuite, au moment de l'exécution, il sait que stooge2 est un Larry et appelle donc la méthode Larry.print (Moe).

etc ...

Informez-moi si suivre tout ce chemin ne vous convient pas.

(mis à jour pour clarifier le prochain)

La règle générale est donc la suivante:

  • le compilateur examine le type de variable pour décider de la méthode à appeler.
  • le moteur d'exécution examine la classe dans laquelle la variable est dirigée pour décider où obtenir la méthode.

Donc quand vous avez:

Moe stooge2 = new Larry();
stooge2.print(new Moe());

le compilateur dit:

  • Larry peut-il être assigné à stooge2? (oui car Larry est une sous-classe de Moe)
  • Moe a-t-il une méthode d'impression (Moe)? (oui)

le runtime dit:

  • Je suis censé appeler la méthode print (Moe) sur cet objet ici ... stooge2
  • stooge2 pointe vers un Larry.
  • J'appellerai la méthode print (Moe) dans la classe Larry.

Une fois que vous avez travaillé, essayez de vous débarrasser de certaines méthodes et voyez comment cela change les choses.

Autres conseils

En réalité, ce problème n’est pas aussi simple qu’il semble, car Java est à la fois lié de manière statique et dynamique. Vous devez comprendre où chacun est appliqué avant de comprendre tous les résultats de cet exercice.

La règle générale mentionnée par TofuBeer n’est correcte que dans le cas de la liaison dynamique. En liaison statique, les décisions ne sont prises qu'au moment de la compilation.

Votre exemple combine la liaison dynamique (lorsque les méthodes sont remplacées) et la liaison statique (lorsque les méthodes sont surchargées).

Regardez à cette question pour plus de détails. .

Un conseil est de ne pas tenir compte de la valeur à gauche lorsque vous regardez des objets. Au lieu de cela, regardez la valeur du droit lors de la déclaration, il s'agit de la valeur réelle de l'objet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top