我希望能够做的是加载一组类,可能都在同一个文件夹中。所有这些都实现了相同的接口并且是同一个类,然后在我的代码中我希望能够在这些类上调用函数。
答案 0 :(得分:5)
根据您对我的问题的回答,您似乎想要定义游戏界面,然后插入任意数量的AI实现,可能是从.properties文件配置的。这是API接口的相当标准的使用。
您定义一个EngineInterface,提供一种接受游戏状态并返回移动的方法。然后定义所有实现EngineInterface的多个类。您的驱动程序读取属性文件以获取实现类的名称,使用Class.forName()实例化它们并将它们存储在列表和/或映射中。然后当驱动程序获得请求时,它依次调用每个实现并跟踪结果。
答案 1 :(得分:2)
你有没有试过像:
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 :(得分:2)
可以使用OSGI执行您想要的操作,但您也可以使用自定义类加载器。我们的想法是,您必须为要加载的类的每个版本实例化一个类加载器。 Here你可以找到一个很好的解释。
但我认为你真正需要解决的问题是基于Jim Garrison或Dave L Delaney描述的界面......
答案 3 :(得分:1)
如果你可以使用OSGI,就像它一样简单 掰手指!在oSGI你可以 有多个相同的经文 类。你所做的一切都是一样的 捆绑包含不同版本。
否则,您仍然可以编写读取这两个类的自定义类加载器。一种方法就是这样。您编写了两个ClassLoader,其中一个加载了该类的一个版本,另一个加载了该类的另一个版本。现在根据需要选择classloader1或classloader2来加载类。所以现在你也可以在内存中同时加载同一个类的多个版本。
注意:确保您确实想要这样做,可能还有其他方法可以解决您的问题。
答案 4 :(得分:1)
我知道的唯一支持你所追求的内容的框架是 OSGI :
在本文“Exposing the boot classpath in OSGi”中描述的网络模型确实允许
网络模型的一个副作用(或目标)是类型隔离或类版本控制:同一类的多个版本可以在同一个VM内很好地共存,因为每个版本都被加载到自己的网络中,即自己的空间。
请参阅此tutorial了解并开始选择OSGI框架(例如Equinox,Knoplerfish或Apache Felix)
答案 5 :(得分:0)
可以使用动态类加载来完成。它不是加载不同版本的类,而是加载超类或接口的不同子类。
重要的步骤是:
(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) {
// ...
}
}
希望这有帮助。
答案 6 :(得分:0)
Jim的回答很好 - 您为要使用的类命名,并且它们都符合通用API。但是,给出的解决方案假定类已经在应用程序的类路径上可用。您可能希望以后能够添加更多实施,例如安装应用程序后。
如果是这种情况,那么您可能需要使用自定义类加载器。例如,您可以允许人们将jar文件放在某个特定文件夹中,并将实现的类名添加到属性文件中。然后,您需要一个自定义类加载器,而不是从该文件夹中的jar加载类,并且您将使用该类加载器来加载类(例如,使用Class.forName(className,classLoader))。
实际上,如果每个jar文件都有一个类加载器,那么您将能够在jar文件中拥有多个具有相同名称的类,因为类加载器定义了类名边界。这几乎是OSGI正在做的事情。
这里有一些与从jar加载类相关的代码:
http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html