6

と呼ばれる基底Aクラスといくつかのサブクラス ( BCDなど) があるとします。ほとんどのサブクラスにはメソッドdo()がありますが、ベースクラスにはありません。ClassAAは と呼ばれるメソッドを提供します。このメソッドは、 またはまたはなどgetObject()のタイプのオブジェクトを作成しますが、オブジェクトを type として返します。BCDA

返されたオブジェクトを具象型にキャストしてそのdo()メソッドを呼び出すにはどうすればよいですか (このメソッドが使用可能な場合)。

編集: クローズド ソース API を使用しているため、 Class 、サブクラス、またはの実装を変更することはできませんAAA。そして、ご覧のとおり、いくつかの設計上の問題があります。

4

8 に答える 8

4

メソッドをテストしinstanceofて呼び出すことができます。do()

A a = aa.getObject();
if (a instanceof B) {
   B b = (B) a;
   b.do();
}
// ...
于 2012-10-01T16:05:25.887 に答える
3

より良いアイデアは、実際にクラスにメソッドを抽象メソッドまたは具体的な空のメソッドとしてA定義させることだと思います。do()これにより、キャストを行う必要がなくなります。

どのクラスも変更することが許可されていない場合は、メソッドを定義するクラスを定義できますが、それMyA extends Aは基本的に何をするか、タイプのオブジェクトを返すだけです....do()MyBMyCMyAAAAMyBMyC

これがうまくいかない場合は、返されたオブジェクトが型であるかどうかを確認Bしてキャストするなどの方法以外に方法がありませんB

于 2012-10-01T16:04:20.163 に答える
1

Aを定義し、それがプライベートでないと仮定すると、返さdoれるサブクラスに関係なく、キャストなしで呼び出すことができAAます。これがポリモーフィズムの特徴の 1 つです。実行時に、インタープリタは の正しい (つまり、実際のクラスの実装) バージョンを使用しdoます。

于 2012-10-01T16:04:28.057 に答える
0

変更は許可されていないがA、サブクラスを変更できる場合は、メソッドdo()とのインターフェースを作成し、すべてのサブクラスにそのインターフェースを実装させることができます。

public interface Doer {
    public void do();
}

public class B extends A implements Doer {
    //implement do method
}

//.. same for other subclass

その後、キャストは必要ありません。それ以外の場合は、明示的なダウンキャストが必要になります。

于 2012-10-01T16:13:27.070 に答える
0

それを行う最良の方法は、Aそのメソッドをクラスに持つことです。ただし、クラスを変更することは許可されていないためです。リフレクションを使用して、すべてのクラスのラッパー インスタンスを作成することをお勧めします。

以下のクラスの静的メソッドは、その方法を示すためだけに使用されます。AをEでラップできる別のインスタンス変数を持つことができます。

public class E {

public static void doMethod(A a) {
    Class<?> class1 = a.getClass();
    Method method;
    try {
        method = class1.getDeclaredMethod("doMethod", null);// B, C, D has doMethod
        method.invoke(a, null);
        // I know to many exceptions
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

}
}

2 番目のオプションはinstance of、型を確認してからキャストする必要があるものです。

于 2012-10-01T17:03:35.757 に答える
0

Derived Classあなたが説明していることは、参照時にメソッドを呼び出したいように思えBase classます..

しかし、そのためには、メソッドも自分で持つ必要がありますbase class..したがって、基本クラスでも
メソッドを宣言する必要があります..実装を提供したくない場合は、抽象化するか、抽象化します空のメソッド..それは問題ではありません..do()A

さて、あなたが説明しているのと同じことをすれば..タイプキャストをする必要はありません..

Derived Classに基づいて適切なメソッドが呼び出されるため、 -which derived class object does your base class reference point to

public abstract class A {
   public abstract void do();
}

public class B extends A {
   public void do() {
       System.out.println("In B");
   }
}

public class Test {
    public static void main(String[] args) {
        A obj = returnA();

        obj.do();  // Will invoke class B's do() method
    }

    /** Method returning BaseClass A's reference pointing to subclass instance **/
    public static A returnA() {
         A obj = new B();
         return obj;
    }
}

わかりました、あなたの編集を見たところ、クラスを変更することはできません..

typecastその場合、返された参照のインスタンスに基づいて実際に実行する必要があります。

したがって、main上記の方法では、A obj = returnA();この行の後に次の行を追加します。

if (obj instanceof B) {
    B obj1 = (B) obj;

}

ただし、この場合、instanceof各サブクラスをチェックする必要があります..それは大きな問題になる可能性があります..

于 2012-10-01T16:09:01.590 に答える
0

まず第一に、Abstract メソッドをClass A使用して抽象クラスとして作成する方が良いdo()方法です......

さらに、あなたがやりたい方法をまだ望んでいるなら..

明示的なキャストを行います。

B b = (B) a; // a is a casted back to its concrete type.

さらに、コンパイラのこの非常に重要な動作に留意する必要があります

The Object Reference Variable of Super Type must have the method to be called, whether the Sub Type Object has or not.

例えば:

A a = new B();

-メソッドを呼び出すdo()Object Reference Variableは、タイプ A の場合、クラスがメソッドA を持っている必要があり go()ます。

于 2012-10-01T16:10:14.733 に答える