1

条件に応じて、2 つの異なるタイプのいずれかのオブジェクトをインスタンス化する必要があります。どちらの型もコンストラクターに同じ引数を取り、どちらもマスター型のサブクラスです。条件内で正しい型への参照を定義し、その参照を使用してオブジェクトをインスタンス化できますか? 簡単な例:

if (v == "bob") {
   Object myType = bobType;
} else {
   Object myType = otherType;
}
SuperType instance = new myType(arg1, arg2);

これは機能しません。Javaでこれの正しい構文はありますか? これは、これを行うためのショートカットです。

if (v == "bob") {
   SuperType instance = new bobType(arg1, arg2);
} else {
   SuperType instance = new otherType(arg1, arg2);
}

私は実際に、すべて同じ型のいくつかのインスタンスを作成していますが、それらはすべて引数の長いリストを取り、型を除いて自分自身を正確に繰り返すことを避けたかったのです。

4

4 に答える 4

3

可能ですが、Reflection API を使用する必要があります。次のように書けない理由があるのでしょうか。

SuperType instance;
if (v == "bob") {
   instance = new bobType(arg1, arg2);
} else {
   instance = new otherType(arg1, arg2);
}

それ以外の場合は、 Class 型を使用してコンストラクターへの参照を取得する必要があります。その後、コンストラクターを直接呼び出すことができます。

  SuperType instance;
  Class<? extends SuperType> clazz;
  Constructor<? extends SuperType> constructor;
  if ("bob".equals(v)) {

       clazz = bobType.class;
    } else {
       clazz = otherType.class;
    }
  //subbing in types of arg1 and arg2 of course
  constructor = class.getConstructor(String.class, String.class);
  instance = constructor.newInstance(arg1, arg2);

したがって、目標が単に簡潔にすることである場合、それほど冗長ではありません。さらに、リフレクションは、処理する必要があるさまざまなチェック済み例外をスローします。コンパイル時にすべての可能な型を知っていても、あまり利点はありません。すべてのタイプを知っているわけではなく、名前で他のライブラリからクラスを検索している場合に役立ちます。

于 2012-10-10T00:17:14.173 に答える
2

これにはリフレクションを使用できますが、ほとんどの場合、ファクトリを定義する方が慣用的です。例えば、

interface MyFactory {
  SuperType newInstance(Foo arg1, Bar arg2);
}

class BobFactory implements MyFactory {
  public BobType newInstance(Foo arg1, Bar arg2) {
    return new BobType(arg1, arg2);
  }
}

class OtherFactory implements MyFactory {
  public OtherType newInstance(Foo arg1, Bar arg2) {
    return new OtherType(arg1, arg2);
  }
}

void myMethod() {
  MyFactory factory;
  if (v == "bob") {
    factory = new BobFactory();
  } else {
    factory = new OtherFactory();
  }
  SuperType instance = factory.newInstance(arg1, arg2);
}

これは想像以上に冗長ですが、BobTypeorのコンストラクターを変更した場合OtherType、実行時にクラッシュするのではなく、このコードを更新する必要があることをコンパイラーがキャッチするという利点があります。

于 2012-10-10T00:23:34.500 に答える
1

Java ではもう少し複雑です。クラス名を使用してインスタンスを作成する必要があります。この質問を見てください:クラス名を使用してインスタンスを作成し、コンストラクターを呼び出す

于 2012-10-10T00:17:35.963 に答える
0

あなたのコード:

if (v == "bob") {
   Object myType = bobType;
} else {
   Object myType = otherType;
}
SuperType instance = new myType(arg1, arg2);

私の理解では、条件に応じてさまざまなタイプをインスタンス化する必要があります。

スコープが if-else 条件を超えるように変数を宣言するか (できれば、オプション #1 と呼びます)、適切な型をインスタンス化するようにファクトリ コンストラクターを作成します (必要になる可能性は低く、次のように思われます)。やり過ぎ、オプション #2)。

オプション1:

宣言を破るだけです。

// declare "instance" so it exists inside if-else AND after condition
SuperType instance; 
if (v == "bob") {
   // instantiate "instance"
   instance = new bobType(arg1, arg2);
} else {
   // instantiate "instance"
   instance = new otherType(arg1, arg2);
}
// "instance" is now instantiated

オプション #2:

背景: http://en.wikipedia.org/wiki/Factory_method_pattern

基本的に行うことは、SuperType 型を構築するためのインターフェイスを作成することです。明らかに、オブジェクトをすぐにインスタンス化できるように、両方のクラス (bobType と otherType) がそれを実装する必要があります。これにより、コード内で「ファクトリー」にアクセスできるようにする必要がなくなるわけではありません。繰り返しの操作でない場合は、オプション #1 を使用することをお勧めします。

于 2012-10-10T00:34:22.250 に答える