2010-10-27 29 views
24

¿Hay alguna forma elegante de hacer que el método Java ubicado dentro de la clase padre devuelva el objeto de la clase secundaria, cuando se llama a este método desde el objeto clase infantil?Forma de hacer que el método de clase padre Java devuelva el objeto de la clase secundaria

Quiero implementar esto sin utilizar interfaces adicionales y métodos adicionales, y usar esto sin bloqueos de clase, argumentos auxiliares, etc.

Actualización:

sentimos que no estaba tan claro.

Quiero implementar el método de encadenamiento, pero tengo problemas con los métodos de la clase principal: pierdo el acceso a los métodos de clases secundarias, cuando llamo a los métodos de clase primaria ... Supongo que he presentado el núcleo de mi idea.

Por lo tanto, los métodos deben devolver el objeto this de la clase this.getClass().

Respuesta

46

Si sólo está buscando encadenamiento método contra una subclase definida, a continuación, el siguiente debería funcionar:

public class Parent<T> { 

    public T example() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return (T)this; 
    } 
} 

que podría ser abstracta si se quiere, a continuación, algunos objetos secundarios que especifican el tipo de retorno genéricos (esto significa que no se puede acceder desde childBMethod Childa):

public class ChildA extends Parent<ChildA> { 

    public ChildA childAMethod() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return this; 
    } 
} 

public class ChildB extends Parent<ChildB> { 

    public ChildB childBMethod() { 
    return this; 
    } 
} 

y luego usarlo como esto

public class Main { 

    public static void main(String[] args) { 
    ChildA childA = new ChildA(); 
    ChildB childB = new ChildB(); 

    childA.example().childAMethod().example(); 
    childB.example().childBMethod().example(); 
    } 
} 

la salida será

org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildB 
org.example.inheritance.ChildB 
+0

Muchas gracias. Esto es exactamente lo que quiero –

+0

@Errandir No hay problema - me alegro de ayudar –

+1

perfecto. Pero necesito agregar '@SuppressWarnings (" unchecked ")' a 'example()'. –

1

sé exactamente a qué se refiere, en Perl no es la variable $class que significa que si se llama a un método de fábrica en una subclase, incluso si no se anula en la subclase, si instanciates cualquier caso de $class una instancia de la subclase será creada.

Smalltalk, Objective-C, muchos otros idiomas tienen una facilidad similar.

Por desgracia, no existe una instalación equivalente en Java.

+0

En Perl no hay tal cosa como una variable de $ class' genérica incorporada en 'en absoluto. ** se puede calcular ** recuperando el primer argumento de un método de clase (por ejemplo, 'MyClass-> mySub()' pasa la llamada '" MyClass "' como primer parámetro) o tomando 'ref()' de objeto (que es un primer argumento de un método llamado a un objeto, por ejemplo '$ myclass_object-> mySub()' pasa '$ myclass_object' como primer parámetro y' ref ($ myclass_object) 'devuelve' "MyClass" ') . Por favor, sepa de lo que está hablando. – DVK

+0

Pero, como dices, el primer argumento para un método de clase siempre es el nombre de la clase en la que se aplicó el método. Esto significa que puede escribir métodos que luego hacen '$ class-> newInstance()' que creará instancias de subclases si se llama al método en una subclase. Útil para métodos de fábrica, patrón de método de plantilla en construcción, etc. En Java, 'static MyObj newInstance() {..}' siempre producirá un 'MyObj' aunque llame a' MySubObj.newInstance() 'y no hay forma de evitarlo, como por ejemplo, en Perl. –

3

simplemente para demostrar:

public Animal myMethod(){ 
    if(this isinstanceof Animal){ 
    return new Animal(); 
    } 
    else{ 

    return this.getClass().newInstance(); 
    } 
} 
+0

Este método debería cambiarse una y otra vez a medida que se agregan, cambian y eliminan subclases. Aún así, una solución, no obstante. – BoltClock

+0

@BoltClock, solo estaba demostrando, he resuelto su problema en esta actualización. –

2

Puede llamar this.getClass() para obtener la clase en tiempo de ejecución.

Sin embargo, esta no es necesariamente la clase que llamó al método (podría estar aún más abajo en la jerarquía).

Y necesitaría usar la reflexión para crear nuevas instancias, lo cual es complicado, porque no sabe qué tipo de constructores tiene la clase secundaria.

return this.getClass().newInstance(); // sometimes works 
+0

Eso suena a: Un padre puede producir un hijo a través de la reflexión, pero no se garantiza que sea suyo. :) –

+0

Va a ser una subclase de la clase actual, porque 'this' siempre es así. Sin embargo, podría ser una subclase indirecta. – Thilo

0
public class Parent { 
    public Parent myMethod(){ 
     return this; 
    } 
} 
public class Child extends Parent {} 

Y invocarlo como

 Parent c = (new Child()).myMethod(); 
     System.out.println(c.getClass()); 

¿Es esta solución es correcta? Si es así, entonces, ¿cómo es diferente de la solución n. ° 1?

7

¿Qué estás tratando de lograr? Parece una mala idea. Una clase de padres no debería saber nada sobre sus hijos. Parece muy cerca de romper el Liskov Substitution Principle. Mi sensación es que su caso de uso sería mejor al cambiar el diseño general, pero difícil de decir sin más información.

Lamento sonar un poco pedante, pero me da un poco de miedo cuando leo tal pregunta.

Cuestiones relacionadas