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

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top