Pregunta

Teniendo en cuenta los siguientes tres clases de cómo puedo utilizar la reflexión para llamar a la función de inicialización de la clase padre (s) y luego la subclase:

public class Test {

    public static void main(String[] args) {
        ExtendedElement ee = new ExtendedElement();
        initialize(ee);
     }

    public static void initialize(Element element) {
        System.out.println(element.getClass());
        initialize(element.getClass());
    }

    public static void initialize(Class clazz) {
        System.out.println(clazz.getClass());
    }
}

public class Element {
    protected String value;
    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
}

public class ExtendedElement extends Element {
    protected String extendedValue;
    public void setExtendedValue(String extendedValue) {
        this.extendedValue = extendedValue;
    }
    public String getExtendedValue() { return extendedValue; }
}

No estoy muy seguro de cómo paramertize la función de inicialización en la clase de prueba, como el parámetro clazz es un tipo de prima.

Lo que esencialmente necesidad es llamar initialize en la jerarquía de clases si lo que pase al initialize es de una subclase de elemento.

Algo parecido a lo siguiente:

public void initialize(Class clazz) { 
    if (Element.class.isInstance(clazz.getClass().getSuperclass()) {
         initialize(clazz.getClass().getSuperclass());
    }
    //Work to call initialize function 
}

Editar 1:

No se puede parametrizar que la función seudo anteriormente de manera diferente para retener el tipo de objeto y luego llamar a la función que necesito?

Lo que estoy tratando de hacer es evitar tener que tener el mismo método anulado para cada una de mis clases y permitir alguna herencia para mi Selenio 2 Page objetos. Lo que tengo que hacer es ser capaz de introspección es la superclase (es) de mi auto e inicializar cada uno de mis WebElement campos antes de ejecutar las pruebas en estos campos.

Estos están siendo inyectados con la primavera, y para complicar aún más las cosas estoy permitiendo que las pruebas que se escriben utilizando un lenguaje de expresión de primavera. Soy carga diferida mis frijoles, y el uso de la interfaz InitializingBean para intentar inicializar mis WebElements antes de su uso a NPE evitar.

tuve que envolver los WebElements con un objeto personalizado para que pudiera inyectar las estrategias de localización utilizando la primavera (Nos reutilizar un montón de piezas, pero tienen diferente ID / nombres de las clases que dependen de donde son utilizados en la aplicación, lo había hecho previamente a mí llegar aquí y no será cambiado en este tiempo a pesar de mis argumentos para mantener la coherencia). Por ejemplo, tenemos un widget de la fecha que tiene diferentes niveles de detalle, a veces necesitamos sólo un mes, a veces meses y años, etc ... Sería bueno si pudiera utilizar una clase abstracta y romper estos puntos en común a su mínimo común denominador y se extienden desde allí. Para hacer eso tengo que ser capaz de hacer lo siguiente en mi clase base:

public abstract class PageObject implements InitializingBean {
    ...
    public void afterPropertiesSet() {
        //Pass in concrete impl we are working with - this allows me to initialize properly
        initializeWebElements(this.getClass());
    }
    ...
    public void initializeWebElements(Class clazz) {
        //This does not grab inherited fields, which also need to be initialized
        for (Field field : clazz.getDeclaredFields()) {
            if (WidgetElement.class == field.getType()) {
                Method getWidgetElement = clazz.getDeclaredMethod("get" +
                    StringUtils.capitalize(field.getName()), new Class [] {});
                    WidgetElement element = 
                      (WidgetElement) getWidgetElement.invoke(this, new Object [] {});
                    element.initElement();
    }
}
¿Fue útil?

Solución 3

Aquí está mi solución temporal, dejando abierta la pregunta de esperar para recoger algunas respuestas mejores, aunque para mi caso de uso.

public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
    Class clazz = this.getClass();
    do {
        initializeElements(clazz);
        clazz = clazz.getSuperclass();
    } while (clazz != null);
}

Otros consejos

No se puede llamar a un método en un nivel específico. Lo único es que tienes acceso a la palabra clave super dentro de la propia clase.

Para realizar este trabajo, al que desea llamar super.initialize() desde dentro de cada subclase, a continuación, sólo llamar a través de la reflexión.

Esto no es C ++, donde puede llamar a un método específico en un determinado nivel de la jerarquía de herencia.

No estoy muy seguro de cómo parametrizar la función de inicialización en la clase de prueba, como el parámetro clazz es un tipo de prima.

No hay nada en su ejemplo se requiere para hacer uso del parámetro de tipo genérico, por lo declare como Class<?>.

No entiendo cuáles son sus métodos initialize realmente están tratando de hacer, pero hay una serie de problemas:

Parece que tienes un método initialize que toma una instancia (de Element) como un argumento, y otro que toma un objeto Class como argumento. Eso es realmente manzanas y naranjas cosas ... y hay que explicar lo que está tratando de hacer.

Su intento de dar contenido a cabo el método contiene lo siguiente:

Element.class.isInstance(clazz.getClass().getSuperclass())

Esto nunca será evaluada como verdadera, porque está preguntando si algún objeto Class es un ejemplo de la clase Element. (Lo que es más, clazz.getClass().getSuperclass() es en realidad va a ser el mismo que java.lang.Object.class. La clase de un objeto Class es java.lang.Class y su superclase es java.lang.Object).

Pero no puedo entender lo que debería ser, ya que no describen claramente lo que usted está tratando de lograr.

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