Question

Compte tenu des trois catégories suivantes comment puis-je utiliser la réflexion pour appeler la fonction d'initialisation de la classe parent (s) et la sous-classe:

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; }
}

Je ne suis pas tout à fait sûr comment paramertize la fonction initialize dans la classe de test, comme le paramètre clazz est un type brut.

Ce que je essentiellement besoin est d'appeler initialize la hiérarchie de classe si ce que je passe dans initialize est une sous-classe de l'élément.

Quelque chose comme ce qui suit:

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

Edit 1:

je ne peux pas la fonction paramétrez pseudo ci-dessus différemment pour conserver le type de l'objet puis appeler la fonction que je dois?

Ce que je suis en train de faire est d'éviter d'avoir à la même méthode remplacée pour chacun de mes cours et permettre un certain héritage pour mon Sélénium 2 Page Objets. Ce que je dois faire est de pouvoir est Introspect la superclasse (es) de mon auto et initialize chacun de mes champs de WebElement avant l'exécution des tests sur ces champs.

Ces sont injectés avec ressort, et les choses compliquent encore j'autorise des tests à écrire en utilisant le langage d'expression Spring. Je suis paresseux mes chargement de haricots, et en utilisant l'interface InitializingBean pour tenter d'initialiser mes WebElements avant leur utilisation afin d'éviter NPE.

Je devais envelopper les WebElements avec un objet personnalisé pour que je puisse injecter les stratégies de localisation à l'aide de printemps (nous réutilisons beaucoup de morceaux, mais ils ont différents ids / noms de classe dépendant de l'endroit où ils sont utilisés dans l'application, ce qui a été fait avant moi venir ici et ne sera pas changé à ce moment malgré mes arguments en faveur de la cohérence). Par exemple, nous avons un widget de date qui a granularités différentes, parfois nous avons juste besoin d'un mois, parfois le mois et l'année, etc ... Ce serait bien si je pouvais utiliser une classe abstraite et de briser ces points communs jusqu'à leur plus petit dénominateur commun et d'étendre à partir de là. Pour ce faire, je dois pouvoir faire ce qui suit dans ma classe de 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();
    }
}
Était-ce utile?

La solution 3

Voici ma solution temporaire, en laissant ouverte la question de recueillir des meilleures réponses, espérons que pour mon cas d'utilisation.

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

Autres conseils

Vous ne pouvez pas appeler une méthode à un niveau spécifique. La seule chose est que vous avez accès au mot-clé super dans la classe elle-même.

Pour faire ce travail, vous voulez appeler super.initialize() à l'intérieur de chaque sous-classe, alors appeler via la réflexion.

Ce n'est pas C ++, où peut appeler une méthode spécifique à un niveau spécifique de la hiérarchie d'héritage.

  

Je ne suis pas tout à fait sûr sur la façon de paramétrer la fonction initialize dans la classe de test, comme le paramètre clazz est un type brut.

Rien dans votre exemple vous oblige à utiliser le paramètre de type générique, donc déclarer comme Class<?>.

Je ne comprends pas ce que vos méthodes initialize sont vraiment essayer de faire, mais il y a un certain nombre de problèmes:

Vous semblez avoir une méthode de initialize qui prend une instance (de Element) comme argument, et un autre qui prend un objet Class comme argument. C'est vraiment des trucs de pommes et des oranges ... et vous avez besoin d'expliquer ce que vous essayez de faire.

Votre tentative de étoffant la méthode contient ceci:

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

Cela n'évalue à vrai, car il demande si un objet est une instance Class de la classe Element. (De plus, clazz.getClass().getSuperclass() va vraiment être le même que java.lang.Object.class. La classe d'un objet Class est java.lang.Class et sa superclasse est java.lang.Object).

Mais je ne peux pas comprendre ce qu'elle devrait être, parce que vous ne décrivez pas clairement ce que vous essayez d'atteindre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top