可以从我的代码中重构另一个包中的Java接口吗?

时间:2011-08-08 18:55:41

标签: java oop inheritance interface package

我在我的Java项目中使用(开源)API并引用它的接口。一个接口(Foo)广泛用于API和使用它的项目中。对于我的项目,我想使用一个只公开Foo方法子集的接口,这样Foo将从我的新接口(Bar)继承方法。我根本不想改变Foo的界面;相反,我希望能够编写实现Bar的类,然后将它们与实现Foo的类一起操作,就好像它们都是Bar一样。

由于API位于不同的包中,有没有办法实现这一点,Bar是所有Foo的超类(接口)?

4 个答案:

答案 0 :(得分:3)

  

我希望能够编写实现Bar的类,然后   操纵那些实现Foo的类,就像它们一样   所有酒吧。

您可以创建一个实现Foo的抽象栏。您将省略两者共享的方法并实现Bar不共享的方法,因此它们会抛出类似UnsupportedOperationException的异常。

但是你不能操纵Foo就好像它是Bar;这是另一种方式。你不能像你提出的那样满足Liskov替代原则。

答案 1 :(得分:2)

您可能需要使用Aspect才能实现此目的。看起来AspectJ有一个@DeclareParents可能会做你想要的。

答案 2 :(得分:2)

您可以使用Adapter Pattern来完成此任务:

public class FooAdapter implements Bar {
   private Foo wrapped;
   public FooAdapter(Foo foo) {
      wrapped = foo;
   }
   public void op1() {
      foo.op1();
   }
   public string op2(int param) {
      return foo.op2(param);
   }
}

答案 3 :(得分:1)

因为Java具有标称类型,因此org.theirs.Fooorg.yours.Foo无关,即使它们具有完全相同的方法签名,我也不认为这可以用于继承在Java中。即使使用泛型,AFAIK也无法说“此方法采用Bar<T extends Foo OR Bar>”的实例。

相反,我认为您想使用Adapter interface来使用您自己的Foo(即FooAdapter,与Foo具有完全相同的签名)并扩展Bar。然后,您可以从Bar中提取FooAdapter中所需的方法。不幸的是,您的代码必须进行修改,以便无处不在您之前引用了他们的Foo,您将改为参考:

  • Bar如果调用的唯一方法是您在界面中定义的方法
  • FooAdapter如果调用Foo中定义但Bar中未定义的方法。

这种方法虽然干净,而且关注点很好,实施起来既痛苦又乏味。我担心。

以下代码片段中显示了这将如何工作的示例:

第三方图书馆

package org.theirs;
public interface Foo {
    void doSomething();
    void doSomethingExtra();
}

您的代码

package org.mine;
public interface Bar {
    void doSomething();
}

public class BarImpl implements Bar{
     public void doSomething( /* implementation */ );
}

public class FooAdapter implements Bar{
    private final Foo adapted;
    public FooAdapter(Foo adapted) {
         this.adapted = adapted;
    }
    public void doSomething() {
        adapted.doSomething(); // delegate to adapted instance
    }
}

public class UsingThoseBars {
    public void doSomethingWithAllThoseBars(Collection<Bar> bars) {
         // each entry in bars could either be a BarImpl or a FooAdapter    
    }
}

您可以从此示例中看到,无法从代码中访问方法doSomethingExtra(),因为接口Bar未指定它。

其他建议

请注意,您可以使用类重写来执行有用的技巧,例如使用AspectJ。我假设你宁愿在编译时获得你想要的效果,纯Java。

另一个建议是让Bar的实施为你不需要的UnsupportedOperationException方法抛出Foo。虽然在主要的Java库中有一个先例(例如JDK中的UnmodifiableList),但我会建议不要使用这种做法。但是,如果用新Foo替换对FooAdapter的引用的成本非常高,那么使用此策略可能是一个很好的折衷。