español java oop overloading double-dispatch

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 :

  1. 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).
  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:

  1. El argumento del método ( this ) es del tipo Parent tiempo de compilación, por lo que se invoca el método print(Parent) .
  2. Si la clase Worker se subclasificó y la subclase anularía ese método, y la instancia del worker 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.