0

注:実際のコードの多くはおそらく混乱を招き、問題とは無関係であるため、これは私の問題の抽象化バージョンです。

すべてが別のクラスから情報を継承するオブジェクトの配列/ArrayListがあります。

例えば

class A

class B extends A

class C extends A

class D extends A

クラスB、C、およびDのオブジェクトはすべて、タイプAの配列に入ります。

それらが出てきたら、特定のメソッド/変数などを使用するために元の型にキャストし直したいと思います。ifステートメントのセットを調べて、どのようなサブクラスを見つける必要がないので、どうすればよいですか。は?クラスAを拡張する新しいクラスを追加するたびに、新しいifステートメントのセットを作成する必要があるため、コードの柔軟性が非常に低くなります。オブジェクトのクラスの正確な名前に簡単に戻る方法はありますか?

4

2 に答える 2

2

オブジェクトのクラスの名前だけが必要な場合は、次を使用できます。

a.getClass().getName(); // or .getSimpleName();

これはa、スーパークラスのタイプとして宣言されている場合でも機能します。あなたの質問のクラス構造を仮定すると:

A a = new B();
System.out.println(a.getClass().getSimpleName());
a = new C();
System.out.println(a.getClass().getSimpleName());

印刷されます:

B
C

編集

コメントで説明するユースケースは、いくつかの方法で処理できます。最も柔軟なのは、複数のディスパッチパターンビジターパターンに関連)です。

  1. インターフェイスを定義する

    パブリックインターフェイスSpriteActor{voidactOn(A anASprite); void actOn(B aBSprite); //など}

  2. でメソッドを定義しAます:

    パブリッククラスA{パブリックボイドacceptActor(SpriteActorアクター){actor.actOn(this); }}

  3. 各Spriteサブクラスでこのメソッドをオーバーライドします。奇妙なことに、各オーバーライドでまったく同じコードを使用できます。これは、コンパイラが呼び出しを実装の正しいオーバーロードされたactOnメソッドにバインドするために必要SpriteActorです。

  4. クライアントコードで、SpriteActorインターフェイスを実装します。actOnオーバーロードされた各メソッドにタイプ固有の呼び出しを実装します。

于 2012-07-08T19:40:48.583 に答える
1

あなたが発見したように、これは醜いです。代わりにポリモーフィズムを使用する必要があります。

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

class B extends A {
    private void foo() { ... }  // Class-specific method
    @Override
    public void doStuff() { foo(); }
}

class C extends A {
    private void bar() { ... }  // Class-specific method
    @Override
    public void doStuff() { bar(); }
}

...

A[] array = { new B(), new C() };

// No casting or conditionals needed!
for (A a : array) {
    a.doStuff();
}
于 2012-07-08T20:14:49.623 に答える