事后实现接口

我认为,以下不能用Java完成。 但我很乐意学习如何实现类似于它的东西。

假设我们有一个C类,它已经在编译代码中使用了。 (我们既不能改变代码也不能改变C的原始定义)。

进一步假设有一些有趣的代码可以重复使用,如果只有C实现接口I.实际上,或许不那么简单,派生D只是C +接口方法的实现。

然而,一旦我有一个C,似乎没有办法说:我希望你成为一个D,也就是说,一个C实现我。

(旁注:我认为如果D是C,那么应该允许c的运行时类型为C的强制转换(D)c,并且C的唯一区别是添加方法。这应该是安全的,如果不是吗?)

怎么能解决这场灾难呢?

(我知道工厂设计模式,但这似乎不是一个解决方案。因为,一旦我们设法在以前是C的所有地方创建D,其他人发现另一个接口J有用并导出E扩展C实现J.但是E和D是不兼容的,因为它们都为C添加了一组不同的方法。所以虽然我们总是可以传递一个预期C的E,但是我们不能通过一个预期D的E.而是,现在,我们需要一个新类F扩展C实现I,J。)

如果您需要兼容的只是接口,那么看看动态代理类没有问题,它基本上是如何在运行时在java中实现接口的。

如果您需要与类类似的运行时兼容性,我建议您查看cglib或javaassist开源库。

难道你不能使用委托类,即包装“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)); 

如果您(可以)管理ClassLoader C类的ClassLoader ,那么您可以尝试使用字节码检测做一些类加载时间shenanigans,以使类实现接口。

当然,在构建期间也可以这样做。 这种方式甚至可能更容易(因为您不需要访问ClassLoader)。

(旁注:我认为如果D是C,那么应该允许c的运行时类型为C的强制转换(D)c,并且C的唯一区别是添加方法。这应该是安全的,如果不是吗?)

一点也不。 如果您可以进行此转换,那么您可以编译试图在此对象上调用“添加的方法”之一的代码,这会在运行时失败,因为该方法在C中不存在。

我想你正在想象演员会从C中检测到“缺失”的方法并自动将它们委托给D. 我怀疑这是否可行,尽管我不能谈论语言设计的含义。

在我看来,你的问题的解决方案是:

定义类D,它扩展C并实现I
定义一个构造函数D(C c),它基本上将给定C对象的状态克隆到一个新的D对象中。
D对象可以传递给你现有的代码,因为它是一个C,它可以传递给想要一个I的代码,因为它是一个我

我相信你想要的是使用java.lang.reflect.Proxy ; 事实上,我已经为当前项目做了类似的事情。 然而,这是相当多的工作,并且由此产生的“混合对象”可以暴露奇怪的行为(因为对它们的方法调用被路由到不同的具体对象,当这些方法试图相互调用时会出现问题)。

我认为你不能这样做,因为Java是严格打字的。 我相信它可以在Ruby和Python等语言中使用mixins来完成。

至于Java,它绝对看起来像是适配器设计模式的一个很好的用法(它早先已经被提出作为“包装器”对象)。