Java - получение всех классов, расширяющих абстрактный класс - PullRequest
0 голосов
/ 12 февраля 2019

Хорошо, я начинаю использовать абстрактные классы, но у меня есть вопрос: у меня есть abstract class Quest.Моя цель состоит в том, чтобы при инициализации объекта new Quest присвоить ему случайный тип Quest (представленный классом, расширяющим Quest).На данный момент мой код:

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

Есть ли способ сделать это автоматически, или просто чище?

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Я бы использовал заводской шаблон.

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();

Вы должны убедиться, что r не больше вашего списка.

0 голосов
/ 12 февраля 2019

Для первой части вопроса, чтобы сделать это автоматически, вероятно, потребуется рефлексия, но для второй части о чистоте, большинство людей сочтут это не очень чистым.

Возможное решениеесли вы согласитесь немного уменьшить область действия до «всех классов, расширяющих 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());
    }
}
0 голосов
/ 12 февраля 2019

Я предлагаю другой подход:

Вы можете сделать свой абстрактный класс Quest an 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
}

Таким образом, вы можете случайным образом выбрать константу перечисления (которая является экземпляром Quest):

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

Единственным недостатком является то, что вы должны поместить всереализации в один файл класса, который может довольно легко запутаться

...