Binding dinamico Java
-
19-08-2019 - |
Domanda
Mi sto esercitando per un esame e ho riscontrato un problema di esempio che mi fa perdere totalmente. Per il seguente codice, trova l'output:
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());
}
}
Avevo in mente le mie idee, ma quando ho gestito Java, ho avuto qualcosa di completamente diverso:
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
I primi sono OK, ma poi non capisco davvero. Qualcuno ha una buona spiegazione per questo problema?
Grazie
Soluzione
Vorrei iniziare disegnando un'immagine ...
Moe - print(Moe)
|
Larry - print(Moe), print(Larry)
|
Curly - print(Moe), print(Larry), print(Curly)
Quindi terrei traccia delle variabili:
- Larry - stooge1 - > Ricci
- Moe - stooge2 - > Larry
- Moe - stooge3 - > Ricci
- Ricci - stooge4 - > Ricci
-
Larry - stooge5 - > Larry
stooge1.print (new Moe ())
- stooge1 - > Curly chiama Curly.print (Moe)
((Curly) stooge1) .print (new Larry ());
- stooge1 - > Curly chiama così Curly.print (new Larry ())
((Larry) stooge2) .print (new Moe ());
- stooge2 - > Larry chiama così Larry.print (new Moe ());
stooge2.print (new Curly ());
Ok, è qui che diventa un po 'più complicato (mi dispiace di averne interrotto uno prima qui)- stooge2 è dichiarato Moe. Quindi, quando il compilatore sta cercando come chiamare, chiamerà il metodo print (Moe). Quindi in fase di esecuzione sa che stooge2 è un Larry, quindi chiama il metodo Larry.print (Moe).
ecc ...
Fammi sapere se seguirlo fino in fondo non funziona per te.
(aggiornato per chiarire il prossimo)
Quindi la regola generale è:
- il compilatore esamina il tipo di variabile per decidere quale metodo chiamare.
- il runtime esamina la classe effettiva a cui punta la variabile per decidere da dove ottenere il metodo.
Quindi quando hai:
Moe stooge2 = new Larry();
stooge2.print(new Moe());
dice il compilatore:
- Larry può essere assegnato a stooge2? (sì, dato che Larry è una sottoclasse di Moe)
- Moe ha un metodo di stampa (Moe)? (Sì)
il runtime dice:
- Dovrei chiamare il metodo print (Moe) su questo oggetto qui ... stooge2
- stooge2 è punto su un Larry.
- Chiamerò il metodo print (Moe) nella classe Larry.
Dopo aver risolto tutto, prova ad eliminare alcuni dei metodi e vedi come questo cambia le cose.
Altri suggerimenti
In realtà, questo problema non è così semplice come sembra, dal momento che Java è sia statico che dinamico. Devi capire dove ciascuno è applicato prima di capire tutti i risultati che stai ottenendo da questo esercizio.
La regola generale menzionata da TofuBeer è corretta solo nel caso di associazione dinamica. Nell'associazione statica, le decisioni vengono prese solo in fase di compilazione.
Il tuo esempio mescola l'associazione dinamica (quando i metodi vengono sovrascritti) e l'associazione statica (quando i metodi sono sovraccarichi).
Dai un'occhiata a questa domanda per maggiori dettagli .
Un suggerimento è di ignorare il valore a sinistra quando si osservano gli oggetti. Invece, guarda il valore di destra durante la dichiarazione, questo è il valore reale dell'oggetto.