事后实现接口

时间:2009-04-15 14:37:28

标签: java design-patterns oop interface

我认为,以下不能用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。)

6 个答案:

答案 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,它绝对看起来像是适配器设计模式的一个很好的用法(它早先已经被提出作为“包装器”对象)。