3

私のクラスは次のようなものです:

class X {}
class Y extends X {};
class Z extends X {};

各サブクラス (id + クラス) の列挙型があります。

enum Type {
   Y_TYPE(1, Y.class), Z_TYPE(2, Z.class);
   int id;
   Class c;
   public Type(int id, Class c) { this.id = id; this.c = c; }
   public static X createInstance() throws Exception {
      return c.newInstance();
   }
}

次に、次のように使用しました。

X parseFromID(int id) {
   for (Type v : Type.values()) {
     if (v.id == id) {
        return v.createInstance();
     }
   }
}

それは正常に動作しますが、これが整数 id に基づいてデータを作成する Java-ist の方法であるかどうか疑問に思っていますか? 探すべき悪いことはありますか?

長い if-else 条件なしで渡されるクラスを X タイプに強制する方法はありますか? 多数のサブクラスがある場合を考えてください。


なぜ整数 ID に取り組みたいのですか?

私はある種のパーサーを書いているので、どこかから取得した整数 ID を適切なオブジェクトに変換する必要があります。

4

3 に答える 3

7

ここでリフレクションを使用する理由はまったくありません。例外をスローすることも悪い習慣であり、リフレクションを使用していなければ、リフレクション例外を処理する必要はありません。あなたは単にすることができます

enum Type {
    Y_TYPE(1) {
        @Override
        public X createInstance() {
            return new Y();
        }
    }, Z_TYPE(2) {
        @Override
        public X createInstance() {
            return new Z();
        }
    };

    private int id;

    private Type(int id) { 
        this.id = id; 
    }

    public abstract X createInstance();
}

これは、すべてのサブクラスに引数なしの public コンストラクターを強制するわけではなく、可能であれば X または Y の同じインスタンスを返すこともできるため、役立ちます。

Java 8 を使用している場合、匿名クラス定義の冗長性が気になる場合は、それらをラムダに置き換えることができます。

import java.util.function.Supplier;

enum Type {
    Y_TYPE(1, X::new), Z_TYPE(2, Y::new);

    private int id;
    private Supplier<X> supplier;

    private Type(int id, Supplier<X> supplier) {
        this.id = id;
        this.supplier = supplier;
    }

    public X createInstance() {
        return supplier.get();
    }
}
于 2015-06-18T19:40:29.853 に答える
2

ファクトリとマップを使用すると、よりアカデミックになります。

import java.util.HashMap;
import java.util.Map;

interface Factory<T> {

    T createInstance();
}

class X {/**/}
class Y extends X {/**/}
class Z extends X {/**/}

class Factories {

   static Map<Integer, Factory<?>> factories = new HashMap<>();
   static {
      factories.put( 1, X::new );
      factories.put( 2, Y::new );
      factories.put( 3, Z::new );
   }

   @SuppressWarnings("unchecked")
   static <T> Factory<T> get( int id ) {
      return (Factory<T>)factories.get( id );
   }
}

public class Main {

   static void main( String[] args ) {
      final Factory<X> fx = Factories.get( 1 );
      final X x = fx.createInstance();
      final Factory<Y> fy = Factories.get( 2 );
      final Y y = fy.createInstance();
      final Factory<Z> fz = Factories.get( 3 );
      final Z z = fz.createInstance();
   }
}
于 2015-06-18T19:47:13.883 に答える
0

長い if-else 条件なしで渡されるクラスを X タイプに強制する方法はありますか?

はい、ジェネリックを使用してクラスを制限できます。コンストラクターを次のように変更します。

public Type(int id, Class<? extends X> c) { this.id = id; this.c = c; }

なぜ整数 ID に取り組みたいのですか? 列挙値を直接使用するか、転送または保存する必要がある場合は文字列表現を使用し、必要に応じて列挙型のvalueOfメソッドを使用して文字列を解析できます。

于 2015-06-18T19:44:36.117 に答える