4

共通のスーパークラスを持つPOJOのセットがあります。これらは、スーパークラス型の2次元配列に格納されます。ここで、配列からオブジェクトを取得し、サブクラスのメソッドを使用したいと思います。これは、それらをサブクラスにキャストする必要があることを意味します。instanceofを使用せずにこれを行う方法はありますか?

更新:具体的な例として:http://obviam.net/index.php/the-mvc-pattern-tutorial-building-games/参照:「敵がクリックされたときに新しいアクション(攻撃)を追加する」

4

5 に答える 5

6

はい-フローを逆にすることでそれを行うことができます。基本クラスのインスタンスが特定のタイプであるときにコードが何かを行う代わりに、アクションアイテムをオブジェクトに渡し、オブジェクトにそれを実行するかどうかを決定させます。これは、VisitorPatternの背後にある基本的なトリックです

interface DoSomething {
    void act();
}
abstract class AbstractBaseClass {
    abstract void performAction(DoSomething ds);
}
class FirstSubclass extends AbstractBaseClass {
    public void performAction(DoSomething ds) {
        ds.act();
    }
}
class SecondSubclass extends AbstractBaseClass {
    public void performAction(DoSomething ds) {
        // Do nothing
    }
}

AbstractBaseClass array[] = new AbstractBaseClass[] {
    new FirstSubclass()
,   new FirstSubclass()
,   new SecondSubclass()
,   new FirstSubclass()
,   new SecondSubclass()
};
for (AbstractBaseClass b : array) {
    b.performAction(new DoSomething() {
        public void act() {
            System.out.println("Hello, I'm here!");
        }
    });
}
于 2012-07-10T14:09:23.650 に答える
4

それらがサブクラスタイプであることがわかっている場合は、チェックせずに直接キャストしてinstanceofください。

しかし、それらをスーパークラス型の配列に入れることは、それらが実際にはサブクラス型であるという情報を破棄するようにコンパイラーに指示しています。スーパークラスがそれらのメソッドを公開するか(おそらく抽象として)、配列がサブクラスタイプである必要があります(したがって、オブジェクトの実際のタイプを忘れるようにコンパイラーに指示しないでください)、またはそれを吸い上げる必要がありますそしてキャストを行います(おそらくinstanceofテストで)。

他の唯一の注目すべき代替案は、ビジターパターンを試してみることです。これは、アクションをオブジェクトに渡し、オブジェクトがそれをどう処理するかを決定できるようにします。これにより、クラスをオーバーライドして、ランタイムタイプに基づいてアクションを無視または実行できます。

于 2012-07-10T14:08:26.103 に答える
2

ビジターデザインパターンの使用を試すことができます。 http://en.wikipedia.org/wiki/Visitor_pattern

なぜそれらの型を知る必要があるのか​​、自問する必要があります。おそらくこれは、スーパークラスの抽象メソッドの使用に置き換えることができ、それらのすべてが目的の結果に従って実装できます。

abstract class A{
    abstract void visit();
}

class B extends A{
    void visit() { print("B"); }
}

class C extends A {
    void visit() { print("C"); }
}
于 2012-07-10T14:09:49.300 に答える
1

そもそもキャストは避けたいと思います。

あなたが何をしようとしているのか、そしてそれらがそのような同じコレクションにあるべきかどうかを本当に考えてください。

あなたがこのようなものを持っているなら

for(MyObj o : array) {
   if(o instanceof A) {
      ((A)o).doA();
   }
   if(o instanceof B) {
      ((B)o).doB();
   }
}

代わりにこれを検討してください

abstract class MyObj {
    abstract void doIt();
}

class A {
    void doIt() { doA(); }
}

class B {
    void doIt() { doB(); }
}
于 2012-07-10T14:11:39.023 に答える
0

スーパークラスのメソッドを公開してから、オーバーライドを使用します。サブクラスが必要に応じてアクションを無視できるように、基本クラスに空の実装を提供します。

于 2012-07-10T14:12:53.423 に答える