我认为,以下不能用Java完成。但我很乐意学会如何实现类似它的东西。
假设我们有一个已经在编译代码中使用的C类。 (我们既不能改变代码也不能改变C的原始定义。)
进一步假设有一些有趣的代码可以重复使用,如果只有C实现接口I.实际上,派生D只是C +接口方法的实现,或多或少是微不足道的。< / p>
然而,一旦我有一个C,似乎没有办法说:我希望你成为一个D,也就是说,一个C实现我。
(旁注:我认为如果D是C,那么应该允许c的运行时类型为C的强制转换(D)c,并且添加C的唯一区别是。这应该是安全的,如果不是的话? )
如何解决这场灾难?
(我知道工厂设计模式,但这似乎不是一个解决方案。因为,一旦我们设法在以前是C的所有地方创建D,其他人发现另一个接口J有用并导出E扩展C实现J.但是E和D是不兼容的,因为它们都为C添加了一组不同的方法。因此,虽然我们总是能够传递一个预期C的E,但是我们无法传递E,而D是预期的。 ,现在,我们需要一个新的类F扩展C实现I,J。)
答案 0 :(得分:10)
难道你不能使用委托类,即包装“C类”实例的新类,还实现“接口I”?
public class D implements I {
private C c;
public D (C _c) {
this.c = _c;
}
public void method_from_class_C() {
c.method_from_class_C();
}
// repeat ad-nauseum for all of class C's public methods
...
public void method_from_interface_I() {
// does stuff
}
// and do the same for all of interface I's methods too
}
然后,如果你需要调用一个通常采用I
类型参数的函数,那就这样做:
result = some_function(new D(c));
答案 1 :(得分:7)
如果所有你需要兼容的是接口那么没问题看看dynamic proxy classes,它基本上是你如何在运行时在java中实现接口。
如果您需要与类类似的运行时兼容性,我建议您查看cglib或javaassist开源库。
答案 2 :(得分:3)
如果您(可以)管理加载您的类ClassLoader
的{{1}},那么您可以尝试使用字节码检测来执行一些类加载时间shenanigans,以使该类实现接口。
当然,在构建期间也可以这样做。这种方式甚至可能更容易(因为您不需要访问ClassLoader)。
答案 3 :(得分:2)
(旁注:我认为演员阵容(D)c, 其中c的运行时类型为C,应该是 如果D是C而且是唯一的,则允许 与C的差异是添加方法。 这应该是安全的,如果不是吗?)
完全没有。如果您可以进行此转换,那么您可以编译试图调用此对象上的“添加方法”之一的代码,这会在运行时失败,因为该方法在C中不存在。
我认为您正在想象演员会从C中检测到“缺失”的方法并自动将它们委托给D.我怀疑这是否可行,尽管我不能谈论语言设计的含义。
在我看来,问题的解决方案是:
定义D类,扩展C并实现I
定义一个构造函数D(C c),它基本上将给定C对象的状态克隆到一个新的D对象中
D对象可以传递给您现有的代码,因为它是C,它可以传递给想要I的代码,因为它是我
答案 4 :(得分:1)
我相信你想要的是java.lang.reflect.Proxy
;事实上,我已经为当前项目做了类似的事情。但是,这是相当多的工作,并且生成的“混合对象”可以暴露奇怪的行为(因为对它们的方法调用被路由到不同的具体对象,当这些方法试图互相调用时会出现问题。)
答案 5 :(得分:0)
我认为你不能这样做因为Java是严格打字的。我相信它可以用Ruby和Python这样的语言来完成,并使用mixins。
至于Java,它绝对看起来像是适配器设计模式的一个很好的用法(它早先已经被提出作为“包装器”对象)。