español - Método de sobrecarga de Java+doble despacho
double dispatch java (2)
¿Alguien puede explicar en detalle la razón por la que se invoca el método sobrecargado de print(Parent parent)
cuando se trabaja con Child
instancia de Child
en mi código de prueba?
¿Alguna especificidad de métodos virtuales o métodos de sobrecarga / resolución en Java involucrados aquí? ¿Alguna referencia directa a Java Lang Spec? ¿Qué término describe este comportamiento? Muchas gracias.
public class InheritancePlay {
public static class Parent {
public void doJob(Worker worker) {
System.out.println("this is " + this.getClass().getName());
worker.print(this);
}
}
public static class Child extends Parent {
}
public static class Worker {
public void print(Parent parent) {
System.out.println("Why this method resolution happens?");
}
public void print(Child child) {
System.out.println("This is not called");
}
}
public static void main(String[] args) {
Child child = new Child();
Worker worker = new Worker();
child.doJob(worker);
}
}
La razón es que doJob
se implementa en Parent
y no se sobrecarga en Child
. Pasa this
a los methos de print
del trabajador, ya que this
es del tipo Parent
Se llamará al método Worker::print(Parent)
.
Para que Worker::print(Parent)
te llame, necesitas sobrecargar doJob
en Child
:
public static class Child extends Parent {
public void doJob(Worker worker) {
System.out.println("from Child: this is " + this.getClass().getName());
worker.print(this);
}
}
En el código anterior this.getClass()
en Child
es equivalente a Child.class
.
Los estados JLS en §8.4.9 Sobrecarga :
- Cuando se invoca un método (§15.12), el número de argumentos reales (y cualquier tipo de argumento explícito) y los tipos de tiempo de compilación de los argumentos se usan, en tiempo de compilación, para determinar la firma del método que se invocará ( §15.12.2).
- Si el método que se debe invocar es un método de instancia, el método real que se invocará se determinará en el tiempo de ejecución, utilizando la búsqueda dinámica de métodos (§15.12.4).
Así que en tu caso:
- El argumento del método (
this
) es del tipoParent
tiempo de compilación, por lo que se invoca el métodoprint(Parent)
. - Si la clase
Worker
se subclasificó y la subclase anularía ese método, y la instancia delworker
era de esa subclase, entonces se invocaría el método anulado.
El doble despacho no existe en Java. Tienes que simularlo, por ejemplo, utilizando el patrón de visitante . Básicamente, en este patrón, cada subclase implementa un método de accept
y llama al visitante con this
como argumento, y tiene como tipo de tiempo de compilación esa subclase, por lo que se utiliza la sobrecarga del método deseado.