2010-02-14 15 views
5

Tengo una clase base llamada Element. Algunas otras clases (como Etiqueta e Imagen) extienden esta clase.Métodos sobrecargados prioridad

ahora tengo una clase de despacho que tiene los siguientes métodos:

public class Dispatcher { 
    public static AbstractPropertyEditor<Label> createEditor(Label e) { 
    ... 
    } 

    public static AbstractPropertyEditor<Element> createEditor(Element e) { 
    ... 
    } 
} 

Si ahora tengo una instancia de etiqueta (que se extiende Element) y quiero pasarlo a createEditor(), ¿por qué es el método más genérico (el segundo) llamado? ¿No sería normal que se llame al método más específico (createEditor(Label e))?

que tienen una necesidad imperiosa el método con el Elemento-param el fin de "atrapar" todas aquellas clases que a) poner en práctica elemento, pero no tienen su propio método específico en esta clase de despacho ..

estoy usando Java 6, ¿cómo "arreglar" esto?

Edit: De acuerdo, tengo que admitir que no es para nada genérico. Pero ahí es donde lo encontré la primera vez.

gracias y saludos

+0

Tiene la instancia asignada a una variable de tipo 'Etiqueta' no' Elemento'? –

+0

(y no de 'T extends Element' donde' T' pasa a ser 'Label'?) –

Respuesta

6

¿Por qué no:

  • hacen Element clase abstracta que proporciona un defecto createEditor() aplicación
  • maquillaje Label anular el createEditor().

Por lo tanto, no necesitará las utilidades estáticas y logrará su objetivo.

Si necesita Element a ser una interfaz, entonces:

  • definen createEditor() como métodos de Element
  • definir una interfaz EditorFactory
  • proporcionan DefaultEditorFactory y ListEditorFactory
  • utilizar las fábricas apropiadas en los implementadores de Element:

    public Editor createEditor() { 
        editorFactory.createEditor(this); 
    } 
    

donde el hormigón se crea una instancia EditorFactory bien durante la inicialización o por medio de algún tipo de dependecy-inyección.


Según su pregunta concreta, depende del tipo que haya compilado allí. Si llama createEditor(obj) que dependerá si se trata de Element obj = .. o Label obj = ..

+0

hmmmm ... tengo que pensar un tiempo sobre las consecuencias que la idea de implementar createEditor en Element y subclases tendría ... en una primera instancia, no parece una mala idea. y en mi situación, podría usarlo de esa manera. Pero, ¿y si aún desea separar esa clase de utilidad estática por razones de separación? ¿Cómo determina Java en mi caso qué método llamar? ¿Siempre llama al más genérico? ¿Hay alguna manera de que se lo llame el más específico? – Atmocreations

+0

actualizó mi respuesta. y ver las respuestas de otros también para el comportamiento exacto. – Bozho

+0

visto, thx. bueno ... el problema es que no me gusta poner esa cosa en una etiqueta justo antes de llamar al método. De lo contrario, podría crear directamente métodos como createLabelEditor (Label l), createImageEditor (Image i), etc. Esto obsoleto el método que tiene Element como parámetro. – Atmocreations

0

Dado que es probable que esté haciendo:

Element element = new Label(); 

se determina por el compilador.

+0

bueno, visto indirectamente (llamando a diferentes métodos según la situación) Estoy haciendo esto, sí. ¿Realmente depende del tipo declarado del elemento var 'para determinar qué método realmente se invoca? ¿No se invoca el método con el tipo "real" (Etiqueta)?Y si no, ¿cuál es el motivo de esto? – Atmocreations

2

Esto realmente tiene poco que ver con los genéricos y todo lo relacionado con la sobrecarga de métodos. En Java, la firma de método llamada se determina en tiempo de compilación, no en tiempo de ejecución, por lo que debe verificar y emitir en tiempo de ejecución.

Así sustituir este:

Element label = getLabel(); 
AbstractPropertyEditor<?> editor = createEditor(label); 

Con esta:

Element label = getLabel(); 
AbtractPropertyEditor<?> editor; 
if(label instanceof Label) { 
     editor = createEditor((Label) label); 
} else { 
     editor = createEditor(label); 
} 

La forma en sí (más estándar/mejor) para solucionar este problema es tener la createEditor método (Elemento) comprobar el tipo y llamar con un molde el método sobrecargado correcto para subtipos. Sin embargo, tendrá un problema con los parámetros de retorno si lo hace en los métodos declarados.

+0

Gracias por la buena respuesta, pero me gustaría evitar 'instanceof' siempre que sea posible. Por lo tanto, esta no es una opción para mí. – Atmocreations

+0

@Atmocreations, luego le sugiero que no use la sobrecarga de métodos con super y subtipos como parámetros. Tal patrón conduce inevitablemente a la instancia de y al lanzamiento. – Yishai

1

Desde el Java Language Specification:

Cuando se invoca un método (§15.12), el número de argumentos reales (y cualquier argumentos de tipo explícitas) y los tipos de tiempo de compilación de los argumentos se usan, en el tiempo de compilación, a determinan la firma del método que se invocará (§15.12.2). Si el método que ha de ser invocado es un método ejemplo, el método real para ser invocada será determinado durante la ejecución tiempo, utilizando el método dinámico de búsqueda (§15.12.4).

+0

thx. pero aunque esto es absolutamente correcto, tampoco me ayuda con el problema actual ni explica la forma en que java determina qué método se llama realmente al final. – Atmocreations

+0

@Atmocreations: Me permito diferir, establece claramente que en el caso de los métodos que no son de instancia, el método invocado será el que corresponda a los tipos de argumentos en tiempo de compilación. Dado que en su caso ese es el elemento que se llama, significa que está llamando al método con un elemento en tiempo de compilación. – JRL

+0

Bien ... bien, discúlpeme. Debo admitir que aún no lo he visto así. – Atmocreations

0

Este es un ejemplo de métodos sobrecargados. Aunque el objeto real en tiempo de ejecución es una etiqueta y no un elemento, la opción de sobrecargar el método para llamar (en otras palabras, la firma del método ) NO se decide dinámicamente en el tiempo de ejecución. El tipo de referencia (no el tipo de objeto) determina qué método sobrecargado se invoca.

Ejemplo

public class Car {  
} 

public class Toyota extends Car {  
} 

public class MyCar { 

    public void run(Car c) { 
     System.out.println("Run any Car"); 
    } 

    public void run(Toyota t) { 
     System.out.println("Run Toyota Car"); 
    } 

    public static void main(String[] args) { 
     MyCar myCar = new MyCar(); 

     Car c1 = new Car(); 
     myCar.run(c1); // Output: Run any Car 

     Toyota c2 = new Toyota(); 
     myCar.run(c2); // Output: Run Toyota Car 

     Car c3 = new Toyota(); 
     myCar.run(c3); // Output: Run any Car  
    } 
} 

Así, en su caso

Element obj1 = new Label(); 
Dispatcher.createEditor(obj); // Method with Element argument is called 
           // as you are passing Element 

Label obj2 = new Label(); 
Dispatcher.createEditor(obj); // Method with Label argument is called 
           // as you are passing Label 

En otra nota, reemplazado invocación de métodos que sucede en tiempo de ejecución y que depende del tipo de objeto (en otras palabras, el tipo de instancia real en el montón)

Cuestiones relacionadas