2009-04-15 33 views
5

我认为,以下是不能用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添加了一组不同的方法。所以虽然我们总是可以传递一个E来预期C,但是我们不能在期望D时传递E。相反,现在,我们需要一个新的类F扩展C实现I,J。)

回答

7

如果所有你需要与兼容的接口,那么没问题看看dynamic proxy classes,它基本上是如何在运行时在java中实现接口的。

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

10

难道你不能使用一个委托类,即一个新类包装一个“C类”的实例,但也实现“界面我”?

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)); 
+0

为什么不简单地“D类扩展C实现I”? – dfa 2009-04-15 15:04:54

+0

,因为它要么用'new D(...)'而不是'new C(...)'来构建,这可能是不可能的。尽管D延伸C,也不可能做“D d =(D)C”。尽管如此,从D到C的向下应该是可能的。 – Alnitak 2009-04-15 15:14:56

+0

我曾试图解释过。 我从不受我控制的代码获取C,并想将它们(不是新的/不同的对象)传递给与接口一起工作的代码。 – Ingo 2009-04-15 15:17:00

3

如果你(能)管理加载您C类,那么你可以尝试做一些类加载时间有心计字节码仪器,使类实现接口的ClassLoader

当然,在构建时也可以做同样的事情。它可能更容易这样(因为你不需要访问ClassLoader)。

1

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

2

(边注:我觉得演员(d)C, 其中c的运行时类型是C,应该 允许如果d是一个C和唯一 差下加入方法 这应该。要安全,不是吗?)

根本不是。如果你能做出这样投,那么你可以编译试图调用该对象的“添加方法”之一,它会在运行时失败,因为该方法不C.

存在,我认为你是想象码演员会检测C中“缺失”的方法并自动将它们委派给D。我怀疑这是否可行,尽管我无法说出语言设计的含义。

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

定义d类,它扩展了C和实现我
定义构造函数d(C C)基本上克隆给定的C对象的状态改变成一个新的D对象。
的d对象可以传递到您现有的代码,因为它是一个C,它可以传递到想要的我,因为它是我

0

我认为你不能这样做,因为Java是代码严格打字。我相信它可以用像Ruby和Python这样的语言来完成,并使用mixin。

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