Pregunta

Estoy practicando para un examen y encontré un problema de muestra que me hace perderme por completo. Para el siguiente código, encuentre cuál es el resultado:

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()); 
    }
}

Tenía mis ideas en mente, pero cuando ejecuté Java, obtuve algo totalmente diferente:

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

Los primeros están bien, pero realmente no entiendo. ¿Alguien tiene una buena explicación para este problema?

Gracias

¿Fue útil?

Solución

Comenzaría dibujando un dibujo ...

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

Entonces haría un seguimiento de las variables:

  • Larry - títere1 - > Rizado
  • Moe - títere2 - > Larry
  • Moe - títere3 - > Rizado
  • Rizado - títere4 - > Rizado
  • Larry - títere5 - > Larry

  • stooge1.print (nuevo Moe ())

    • títere1 - > Curly llama Curly.print (Moe)
  • ((Curly) stooge1) .print (new Larry ());

    • títere1 - > Curly llama Curly.print (nuevo Larry ())
  • ((Larry) stooge2) .print (nuevo Moe ());

    • títere2 - > Larry lo llama Larry.print (new Moe ());
  • stooge2.print (new Curly ());
    Ok, aquí es donde se pone un poco más complicado (lo siento, detuve uno antes aquí)

    • stooge2 se declara ser un Moe. Entonces, cuando el compilador está mirando cómo llamarlo, llamará al método print (Moe). Luego, en tiempo de ejecución, sabe que stooge2 es un Larry, por lo que llama al método Larry.print (Moe).

etc ...

Avísame si seguir eso hasta el final no funciona para ti.

(actualizado para aclarar el siguiente)

Entonces, la regla general es:

  • el compilador observa el tipo de variable para decidir qué método llamar.
  • el tiempo de ejecución examina la clase real a la que apunta la variable para decidir de dónde obtener el método.

Entonces cuando tienes:

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

el compilador dice:

  • ¿se puede asignar a Larry a stooge2? (sí, ya que Larry es una subclase de Moe)
  • ¿Moe tiene un método de impresión (Moe)? (sí)

el tiempo de ejecución dice:

  • Se supone que debo llamar al método print (Moe) en este objeto aquí ... stooge2
  • stooge2 es apuntar a un Larry.
  • Llamaré al método print (Moe) en la clase Larry.

Una vez que haya resuelto todo eso, intente deshacerse de algunos de los métodos y vea cómo eso cambia las cosas.

Otros consejos

En realidad, este problema no es tan simple como parece, ya que Java está a la vez estático y vinculado dinámicamente. Debe comprender dónde se aplica cada uno antes de comprender todos los resultados que obtiene de este ejercicio.

La regla general mencionada por TofuBeer solo es correcta en el caso de enlace dinámico. En el enlace estático, las decisiones solo se toman en tiempo de compilación.

Su ejemplo mezcla el enlace dinámico (cuando se anulan los métodos) y el enlace estático (cuando los métodos están sobrecargados).

Eche un vistazo en esta pregunta para obtener más detalles .

Una sugerencia es ignorar el valor de la izquierda al mirar objetos. En cambio, mire el valor de la derecha durante la declaración, este es el valor real del objeto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top