1

次の3つのクラスがある場合、リフレクションを使用して親クラスの初期化関数を呼び出し、次にサブクラスを呼び出すにはどうすればよいですか。

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

clazzパラメーターはraw型であるため、Testクラスのinitialize関数をパラメーター化する方法がよくわかりません。

基本的に必要なのは、initializeに渡すものがElementのサブクラスである場合、クラス階層のinitializeを呼び出すことです。

次のようなもの:

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

編集1:

上記の疑似関数を別の方法でパラメーター化して、オブジェクトのタイプを保持してから、必要な関数を呼び出すことはできませんか?

私がやろうとしているのは、クラスごとに同じメソッドをオーバーライドする必要がないようにし、Selenium2ページオブジェクトの継承を許可することです。私がする必要があるのは、自分のスーパークラスをイントロスペクトし、これらのフィールドでテストを実行する前に、各WebElementフィールドを初期化することです。

これらにはSpringが注入されており、さらに複雑にするために、Spring式言語を使用してテストを記述できるようにしています。Beanを遅延読み込みし、InitializingBeanインターフェースを使用して、NPEを回避するために、使用する前にWebElementsを初期化しようとしています。

Springを使用してロケーション戦略を挿入できるように、WebElementsをカスタムオブジェクトでラップする必要がありました(多くの部分を再利用しますが、アプリケーションで使用される場所に応じてID/クラス名が異なります。これは以前に行われました。私がここに来ると、一貫性についての私の議論にもかかわらず、現時点では変更されません)。たとえば、さまざまな粒度の日付ウィジェットがあります。月だけが必要な場合もあれば、月と年が必要な場合もあります。抽象クラスを使用して、これらの共通点を最小公分母に分解できれば便利です。そこから拡張します。そのためには、基本クラスで次のことができる必要があります。

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();
    }
}
4

3 に答える 3

2

特定のレベルでメソッドを呼び出すことはできません。唯一のことはsuper、クラス自体の内部のキーワードにアクセスできることです。

これを機能させるには、super.initialize()各サブクラス内から呼び出してから、リフレクションを介して呼び出すだけです。

これはC++ではなく、継承階層の特定のレベルで特定のメソッドを呼び出すことができます。

于 2010-11-16T03:57:26.987 に答える
0

これが私の一時的な解決策です。私のユースケースでは、質問を開いたままにして、より良い回答を収集できることを願っています。

public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
    Class clazz = this.getClass();
    do {
        initializeElements(clazz);
        clazz = clazz.getSuperclass();
    } while (clazz != null);
}
于 2010-11-16T13:48:40.623 に答える
0

I'm not quite sure on how to parameterize the initialize function in the Test class, as the clazz parameter is a raw type.

Nothing in your example requires you to make use of the generic type parameter, so declare it as Class<?>.

I don't understand what your initialize methods are really trying to do, but there are a number of problems:

You seem to have one initialize method that takes an instance (of Element) as an argument, and another that takes a Class object as an argument. That's really apples and oranges stuff ... and you need to explain what you are trying to do.

Your attempt at fleshing out the method contains this:

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

This will never evaluate to true, because it is asking if some Class object is an instance of the Element class. (What is more, clazz.getClass().getSuperclass() is actually going to be the same as java.lang.Object.class. The class of a Class object is java.lang.Class and its superclass is java.lang.Object).

But I can't figure out what it should be, because you don't clearly describe what you are trying to achieve.

于 2010-11-16T05:17:44.447 に答える