Java: динамично загрузите несколько версий того же класса

Вы могли бы хотеть сделать это, когда "внутренний" класс является одноразовым, которое никогда не будет использоваться вне определение внешнего класса. Например, для использования метакласса иногда удобно сделать

class Foo(object):
    class __metaclass__(type):
        .... 

вместо того, чтобы определить метакласс отдельно, если Вы только используете его однажды.

Единственное другое время я использовал вложенные классы как этот, я использовал внешний класс только в качестве пространства имен для собирания в группу набора тесно связанных классов:

class Group(object):
    class cls1(object):
       ...

    class cls2(object):
       ...

Тогда от другого модуля, можно импортировать Группу и назвать их Группой cls1, Группой cls2 и т.д. Однако, можно было бы утверждать, что можно выполнить точно то же (возможно, менее запутывающим способом) при помощи модуля.

6
задан Raedwald 13 October 2016 в 16:08
поделиться

6 ответов

На основании вашего ответа на мой вопрос , кажется, вы хотите определить игровой интерфейс, а затем подключить любое количество реализаций ИИ, вероятно, настроенных из файла .properties. Это довольно стандартное использование интерфейса API.

Вы определяете EngineInterface, предоставляющий метод, который принимает состояние игры и возвращает ход. Затем вы определяете несколько классов, которые реализуют EngineInterface. Ваш драйвер читает файл свойств, чтобы получить имена классов реализации, создает их экземпляры с помощью Class.forName () и сохраняет их в списке и / или на карте. Затем, когда драйвер получает запросы, он по очереди вызывает каждую реализацию и отслеживает результаты.

Вы определяете EngineInterface, предоставляющий метод, который принимает состояние игры и возвращает ход. Затем вы определяете несколько классов, которые реализуют EngineInterface. Ваш драйвер читает файл свойств, чтобы получить имена классов реализации, создает их экземпляры с помощью Class.forName () и сохраняет их в списке и / или на карте. Затем, когда драйвер получает запросы, он по очереди вызывает каждую реализацию и отслеживает результаты.

Вы определяете EngineInterface, предоставляющий метод, который принимает состояние игры и возвращает ход. Затем вы определяете несколько классов, которые реализуют EngineInterface. Ваш драйвер читает файл свойств, чтобы получить имена классов реализации, создает их экземпляры с помощью Class.forName () и сохраняет их в списке и / или на карте. Затем, когда драйвер получает запросы, он по очереди вызывает каждую реализацию и отслеживает результаты.

5
ответ дан 9 December 2019 в 22:36
поделиться

Вы пробовали что-то вроде:

class Move;   // some data type that is able to represent the AI's move.

interface AI {

    Move getMove( GameState state);
};

AIOne implements AI;
AITwo implements AI;

Каждый класс будет реализовывать свой собственный алгоритм для генерации движения, но будет вызываться, но вызываться общим методом

2
ответ дан 9 December 2019 в 22:36
поделиться

It is possible to do what you want with OSGI but you could as well use a custom classloader. The idea is that you have to instanciate a classloader for every version of the class you want to load. Here you can find a good explanation.

But I think what you really need to solve your problem is something based on interfaces like described by Jim Garrison or Dave L Delaney...

2
ответ дан 9 December 2019 в 22:36
поделиться
  1. Если вы умеете использовать OSGI, это очень просто. щелкнув пальцем! В oSGI вы можете иметь несколько версий одного и того же учебный класс. Все, что у вас есть, это то же самое пакеты с разными версиями.

  2. В противном случае вы все равно можете написать свой собственный загрузчик классов, который считывает оба класса. Один из способов сделать это - вот так. Вы пишете два ClassLoader, один из которых загружает одну версию класса, а другой загружает другую версию класса. Теперь, исходя из необходимости, вы выбираете загрузчик классов1 или загрузчик классов2 для загрузки класса. Так что теперь у вас также может быть несколько версий одного и того же класса, загруженных одновременно в память.

Примечание: Убедитесь, что это действительно вы хотите сделать, могут быть другие способы решения вашей проблемы.

1
ответ дан 9 December 2019 в 22:36
поделиться

Единственный известный мне фреймворк, который поддерживает то, что вам нужно, это OSGI :

alt text

Его сетевая модель, описанная в этой статье » Открытие пути к классам загрузки в OSGi ", действительно допускает, что

Одним из побочных эффектов (или целей) сетевой модели является изоляция типов или управление версиями классов: несколько версий одного и того же класса могут прекрасно сосуществовать внутри одной виртуальной машины, поскольку каждая из них загружается в свою собственную сеть, свое собственное пространство.

См. этот учебник для начала и выберите один из элементов OSGI Framework (например, Equinox , Knoplerfish или Апач Феликс )

1
ответ дан 9 December 2019 в 22:36
поделиться

Это можно сделать с помощью динамической загрузки классов. Это не загрузка класса другой версии, а разных подклассов суперкласса или интерфейса.

Важные шаги:

(1) Используйте Class.forName (...), чтобы загрузить класс по имени. Класс должен находиться в пути к классам.

(2) Используйте aClass.newInstance () для создания экземпляра объекта. Это просто, если для конструктора не требуются параметры.

Следующий код должен дать вам некоторое представление. Он не обрабатывает исключения, которые вы должны делать.

class Context {
    void moveUp();
    void moveDown();
    ...
}

interface AI {
    void action(Context con);
}

public class Game {
    public Game() {
        Context  aContext    = new Context();
        String[] aAIClsNames = this.getAIClassNames("ai.list");
        AI[]     aAIs        = this.loadAI(aAIClsNames);
        this.run(aAIs);
    }
    String[] getAIClassNames(String pAIClassListFile) {
        // .. Load the file containning the AI-class file names
    }
    AI[] loadAI(String[] pAIClsNames) {
        AI[] AIs = new AI[pAIClsNames.length];
        for(int i = 0; i < pAIClsNames.length; i++) {
            String    aAIClsName       = pAIClsNames[i];

            // (1) Get the class by name
            Class<? extends AI> aAICls = Class.forName(aAIClsName);

            // (2) Notice the cast as all of class in the list must implements AI
            AIs[i] = (AI)aAICls.newInstance();
        }
        return AIs;
    }
    void run(AI[] pAIs) {
        // ...
    }
}

Надеюсь, это поможет.

0
ответ дан 9 December 2019 в 22:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: