简体   繁体   English

Java-获取扩展抽象类的所有类

[英]Java - Getting all the classes that extend an Abstract Class

Okay, so I'm starting to use Abstract classes, but I have a question : I have this abstract class Quest . 好的,所以我开始使用Abstract类,但是我有一个问题:我有这个abstract class Quest My objective is to, when initializing a new Quest object, give it a random Quest type (Represented by a class extending Quest). 我的目标是在初始化new Quest对象时,给它一个随机的Quest类型(由扩展Quest的类表示)。 For now my code is : 现在我的代码是:

switch (r) {
    case 0:
        quest = new Bandit_Raids2();
        break;
    case 1:
        quest = new Bandit_Raids();
        break;
    case 2:
        quest = new Escort_Mission();
}

Is there any way to do this automatically, or just cleaner ? 有什么方法可以自动执行此操作,或者只是更清洁?

I propose a different approach: 我提出了另一种方法:

You could make your abstract class Quest an enum , and then implement the abstract methods in each enum constant (below is just an example): 您可以将抽象类Quest一个enum ,然后在每个枚举常量中实现abstract方法(下面仅是一个示例):

public enum Quest {
    ESCORT_MISSION {
        public void start(){/* escort something */}
    },
    BANDIT_RAIDS{
        public void start(){/* raid bandits */}
    },
    BANDIT_RAIDS2{
        public void start(){/* raid bandits, again */}
    };

    public abstract void start();

    // add here other methods and/or constructors and/or fields
}

That way you could then randomly select an enum constant (which is an instance of Quest ): 这样,您就可以随机选择一个枚举常量(这是Quest一个实例):

Quest[] values = Quest.values();
int randomIndex = ThreadLocalRandom.current().nextInt(values.length);
Quest quest = values[randomIndex];

The only downside to this is that you have to put all the implementations into a single class file, which can get quite messy, quite easily 唯一的缺点是,您必须将所有实现都放入一个类文件中,该文件可能会变得很乱,很容易

For the first part of the question, to do such thing in an automatic way will probably require reflexion but for the second part about being clean, most people will find it not that clean. 对于问题的第一部分,以自动方式进行此类操作可能需要反思,但是对于第二部分,大多数人会发现它不是那么清洁。

A possible solution if you agree to reduce a little the scope to "all classes that extends Quest" would be to have some static initializer method on all subclasses of Quest to register themself as a possible Quest and having a generic way to create instance for them something like 如果您同意缩小“扩展Quest的所有类”的范围,可能的解决方案是在Quest的所有子类上都具有一些静态初始化方法,以将其自身注册为可能的Quest并采用通用的方式为其创建实例就像是

public abstract class Quest {
    private static final List<Supplier<Quest>> suppliers = new ArrayList<>();

    protected static void register(Supplier<Quest> questSupplier) {
        suppliers.add(questSupplier);
    }

    public static Quest createQuest(){
        int r = 0; // replace by the random call you want there
        return suppliers.get(r).get();
    }
}




public class BanditQuest extends Quest{
    static {
        Quest.register(() -> new BanditQuest());
    }
}

I would use the factory pattern. 我会使用工厂模式。

public abstract class Quest {
    // some generic code
}

public class BanditQuest extends Quest {
    // some specific code
}

public interface Factory {
    Quest create();
}

public class BanditFactory implements Factory {
    @Override
    public Quest create() {
        return new BanditQuest();
    }
}

List<Factory> factories = new ArrayList<Factory>();
factories.add(new BanditFactory());
// add all factories here

Quest quest = factories.get(r).create();

You need to make sure that r is not bigger than your list though. 但是,您需要确保r不大于列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM