是否可以在Java中实现运行时的接口?
我正在处理一个项目,其中有很多由库创建的对象,并且我无法访问这些对象的创建过程。
以下片段作为一个很好的例子来说明我的问题。
法典:
public class Clazz {
//The contents of Clazz are irrelevant
//Clazz is NOT my class. I have no access to its internal structure.
//However, I do have access to Clazz objects that were created elsewhere.
}
ExampleInterface
是 Clazz 在编译时可能实现也可能不实现的接口。
法典:
public interface ExampleInterface {
public void run();
}
下面的代码是我遇到的问题。请注意以下事项:
-
run()
仅当 c 是 的实例时才调用。ExampleInterface
-
getRunConditions(Clazz c)
并且都是我无权访问的类中的私有方法。executeClazz(Clazz c)
- 在编译时,将不包含名为 的方法。
Clazz
run()
- 示例执行器不是我的类。我无法以任何方式访问它(我甚至无法获得该类的实例)。
法典:
public class ExampleExecutor {
public void executeClazz(Clazz c) {
if ((c instanceof ExampleInterface) && getRunConditions(c)) {
ExampleInterface ex = (ExampleInterface) c;
ex.run();
}
}
}
显然,以下方法在语法上是不可能的,但这是我试图实现的。基本上,如果 c 还没有实现,则将 c 设置为实现,然后提供必须重写的方法。ExampleInterface
ExampleInterface
请注意以下事项:
-
extendInterface(
接口的名称
是我为说明我的目标而创建的虚构语法。)
-
run()
必须在此处定义(在运行时)。 - 我不能使用包装器或代理类作为解决方案。IE,对象必须最终实现,我不能使用解决方法。(如果您想知道原因,请参阅此链接)。
Clazz
ExampleInterface
法典:
public void implementInterface(Clazz c) {
if (!(c instanceof ExampleInterface)) {
c.extendInterface(ExampleInterface {
@Override
public void run() {
//code
}
});
}
}
为了澄清,我遇到的问题是,我需要始终知道何时被调用。如果不实现,我不知道什么时候应该调用。run()
Clazz
Clazz
ExampleInterface
run()
同时,我还想偶尔添加对默认情况下不支持的支持。由于我无权创建对象,因此我无法通过自己实现接口来执行此操作。run()
Clazz
问题:简而言之,是否可以在运行时实现接口(并提供所需的方法)?
注意:虽然唯一的解决方案可能需要反射(如果是这样,请在下面发布),但我使用的库有一个安全管理器,可以阻止所有反射的使用。IE,一个反思性的解决方案将来可能对其他人有用,但对我来说毫无用处。
另外,我并不是说只是在我自己的程序中使用库。一个已经运行的宿主应用程序(这就是我使用的库的用途)符合并运行我为其编写的代码。如果该应用程序不喜欢我提供的任何代码(IE,与其安全管理器冲突),则代码甚至永远不会被编译。
为什么我需要这样做:
这与我正在使用的库有关。因为这是一个我无法访问的方法,我无法控制Clazz的创建,我无法确定何时执行。ExampleExecutor
run()
我需要知道何时执行的原因是,实际上,它是我正在使用的库的一部分的事件处理程序。run()
run()
例如:可能是接口的一部分的方法。有时,当鼠标被点击时,我正在处理的实例会小心翼翼地工作(因此会继承),而其他时候则不会。mouseClicked(CustomMouseEvent evt)
CustomMouseListener
Clazz
CustomMouseListener
与实例不同,我总是关心是否单击鼠标,并且始终需要触发事件。Clazz
实际上,实际上是以下内容:ExampleInterface
public interface CustomMouseListener {
public void mouseClicked(CustomMouseEvent evt);
public void mousePressed(CustomMouseEvent evt);
public void mouseReleased(CustomMouseEvent evt);
//etc
}