Java 获取继承您的第三方类的实例
所以情况是这样的:我正在创建一个多人游戏,我希望我的朋友能够为它创建机器人。所以我要做的是创建一个Java 获取继承您的第三方类的实例,java,oop,inheritance,Java,Oop,Inheritance,所以情况是这样的:我正在创建一个多人游戏,我希望我的朋友能够为它创建机器人。所以我要做的是创建一个抽象类Bot{},为Bot定义函数,然后它们必须实现它们:非常简单 我陷入困境的地方是,如何在之后添加它们?您可以使用反射或类似的方法来查找Bot的所有继承者吗?或者我需要搜索.jar文件吗 到目前为止,我是这样做的(简化了,类不在同一个文件中,等等): 然后当我需要每个机器人中的一个时: ArrayList<Bot> bots = new ArrayList<>(); bo
抽象类Bot{}
,为Bot定义函数,然后它们必须实现它们:非常简单
我陷入困境的地方是,如何在之后添加它们?您可以使用反射或类似的方法来查找Bot
的所有继承者吗?或者我需要搜索.jar文件吗
到目前为止,我是这样做的(简化了,类不在同一个文件中,等等):
然后当我需要每个机器人中的一个时:
ArrayList<Bot> bots = new ArrayList<>();
bots.add(new Bot1());
//...
ArrayList bots=new ArrayList();
添加(新的Bot1());
//...
我的问题是,如果我要使用它,因为Bot1
实例是硬编码的,我需要允许人们修改我的代码来添加他们自己的机器人程序,这是我不想要的
我的问题是,我如何在没有硬编码的情况下实现这一点?我知道这是可能的,就像Minecraft做的那样(mods之类的),但我不知道怎么做。到目前为止,我的研究没有得到任何结果(可能是因为我不知道如何用一句简单的话来解释这一点……),所以欢迎提供任何提示,以及学习如何做的地方
此外,我对OOP等有很好的理解,但我对反射和
getClass()
事物完全陌生…从我在本主题中所读到的内容来看,除了在检查每个类是否是Bot的子类的同时通过“蛮力”遍历每个类之外,似乎没有其他真正的方法
要回答您的问题,这是可能的,并且在上述主题中进行了描述 如果您使用的是Spring,您可以请求用@Component注释Bot实现,以便您的应用程序可以使用组件扫描,然后使用
@Autowired private List Bot代码>访问它们。这可能不是您要求的,但在运行时尝试计算给定类的所有子类在我看来不是一个好主意。
为什么不为您的朋友提供注册他们的Bot
实例的便利,就像他们希望通过singleton注册的那样:
public enum BotHolder {
BOTS;
private final List<Bot> bots = new ArrayList<>();
public void registerBot(Bot bot) {
bots.add(bot);
}
public List<Bot> get() {
return bots;
}
}
公共枚举BotHolder{
机器人;
私有最终列表bots=new ArrayList();
公共无效登记点(Bot){
添加(bot);
}
公共列表get(){
返回机器人;
}
}
最简单的方法(没有任何外部框架)可能是将Bot
定义为一个接口(,服务提供商接口),然后使用JRE附带的内置机制。然后需要部署自定义的Bot
实现(作为jar),以便可以在应用程序的类路径上访问它们
比如说:
SPI合同:
public interface Bot {
int play();
}
实现(这需要打包到一个JAR中,该JAR具有链接文档中指定的目录结构,包括META-INF
文件夹):
查找:
import java.util.ServiceLoader;
public class BotResolver {
private final ServiceLoader<Bot> loader;
public BotResolver() {
loader = ServiceLoader.load(Bot.class);
}
/**
* Gets all bot implementations that are currently available in the classpath.
*/
public List<Bot> getAllBots() {
List<Bot> allBots = new ArrayList<>();
Iterator<Bot> it = loader.iterator();
while (it.hasNext()) {
allBots.add(it.next());
}
return allBots;
}
}
导入java.util.ServiceLoader;
公共类BotResolver{
私人最终服务装载机;
公共冲突解决程序(){
loader=ServiceLoader.load(Bot.class);
}
/**
*获取类路径中当前可用的所有bot实现。
*/
公共列表getAllBots(){
List allBots=new ArrayList();
迭代器it=loader.Iterator();
while(it.hasNext()){
allBots.add(it.next());
}
返回所有机器人程序;
}
}
米克的回答很好
下面是我的解决方案(不是使用ServiceLoader
API,而是使用类似的方法)
声明一个属性文件,其属性名BotClasses=
后跟
您朋友的bot类的完全限定路径。(适用于多个
类通过一些分隔符将它们分开,如;
)
通过使用分隔符拆分属性值来迭代BotClasses
属性值,然后对每个完全限定的类名使用:
Bot newObj=(Bot)
Class.forName(strFullyQualifiedClassName).newInstance()
只有在Bot
实现中有默认的/nor arg构造函数时,这才有效。您可以让您的朋友创建实现您的Bot接口的Bot类,然后将它们全部放在一个文件夹中,并使用classLoader.loadClass加载文件夹中的每个类。使用instanceof检查每个类是否实现了所需的接口,如果没有,则放弃它们。
我在本周早些时候写了一个简单的插件系统来尝试这一点,但是现在还没有访问代码,但是关于如何使用所有这些元素的信息是现成的,祝你好运 这里有很多想法:还有:看看工厂设计模式。然后你可以使用reflection
来加载类。我已经使用Netbeans不到一个月了,所以(假设Spring是@comments),我还不熟悉这个。谢谢你的提示,我很快会查的。
public class MyBot implements Bot {
@Override
public int play() {
// do something
}
}
import java.util.ServiceLoader;
public class BotResolver {
private final ServiceLoader<Bot> loader;
public BotResolver() {
loader = ServiceLoader.load(Bot.class);
}
/**
* Gets all bot implementations that are currently available in the classpath.
*/
public List<Bot> getAllBots() {
List<Bot> allBots = new ArrayList<>();
Iterator<Bot> it = loader.iterator();
while (it.hasNext()) {
allBots.add(it.next());
}
return allBots;
}
}