2017-01-16 4 views
4

抽象クラスのすべての子を動的にインスタンス化する方法はありますか?与えられた抽象親クラスのすべての子を動的にインスタンス化する

私が現在持っていることは次のようになります。

public abstract class Command { 

    protected String name; 
    protected String arguments; 

    protected abstract void execute(); 

} 

しかし、私はせずにコマンドを拡張するすべてのクラスをインスタンス化したい場合はどのような抽象親クラスであること、このようなもので

public class CommandHandler { 

    private Command info  = new Info(); 
    private Command prefix  = new Prefix(); 
    private Command roll  = new Roll(); 
    private Command coin  = new Coin(); 
    private Command invite  = new Invite(); 
    private Command quit  = new Quit(); 
    private Command restart  = new Restart(); 

} 

それらを個別にすべて入力し、コマンドを追加するたびにリストに追加しますか?

私はそれらを動的にインスタンス化することができます、私も動的にそれらを操作できますか?すなわち、インスタンス化されたリストに各クラスを追加する。

または、私がより簡単な方法で欲しいものを達成するための優れたデザインがありますか?

EDIT:@ Ashのソリューションは、IDEで完全に動作しますが、jarを使用すると動作しません。あなたはそれが両方で動作するようにしなければならないのは、

classPathList.addAll(ClasspathHelper.forJavaClassPath()); 

それが誰かの役に立てば幸いに変更

classPathList.addAll(ClasspathHelper.forClassLoader()); 

です!

+2

「Command」サブクラスを自分で作成するとどうなりますか?あなたの 'CommandHandler'はそのクラスについてどのように知っていますか? (答えは:いいえ、コードを書くときに考えられるすべてのサブクラスを知ることはできません)。コンパイル時にさまざまなサブクラスが実際に分かっている場合は、 'enum'を使うことを考えましたか? – aioobe

+0

これは役立つ可能性がありますhttp://stackoverflow.com/q/492184/4338417 –

+0

@aioobe Javaはこの種の問題を反映しています。実行時に他のクラスが利用可能かどうかを判断することは可能です。 – Elemental

答えて

4

あなたが(ない場合は、あなたがすべき:P)Mavenを使用する場合は、以下の依存関係を追加します。

<dependency> 
    <groupId>org.reflections</groupId> 
    <artifactId>reflections</artifactId> 
    <version>0.9.10</version> 
</dependency> 

その後、次のコードをしたいクラスを一覧表示することができます(あなたがいないとコンストラクタを持っていると仮定パラメータ):

public class Loader { 

    public static void main(String[] args) { 
     try { 
      Set<URL> classPathList = new HashSet<URL>(); 
      classPathList.addAll(ClasspathHelper.forClassLoader()); 
      Set<Class<? extends Command>> result = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner()).setUrls(classPathList)).getSubTypesOf(Command.class); 

      List<Command> commands = new ArrayList<Command>(); 

      for (Class<? extends Command> c : result) { 
       System.out.println(c.getSimpleName()); 
       commands.add(c.newInstance()); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

それは完璧に動作します!ありがとう。私はそのようなことが存在するのか知らなかった。 また、Mavenを使いたくない人は、reflections-0.9.10.jar、javassist-3.19.0-GA.jar、guava-15.0.jar、およびアノテーション2.0.1.jar。 – Svetroid

関連する問題