我在我的Java项目中使用(开源)API并引用它的接口。一个接口(Foo
)广泛用于API和使用它的项目中。对于我的项目,我想使用一个只公开Foo
方法子集的接口,这样Foo
将从我的新接口(Bar
)继承方法。我根本不想改变Foo
的界面;相反,我希望能够编写实现Bar
的类,然后将它们与实现Foo
的类一起操作,就好像它们都是Bar
一样。
由于API位于不同的包中,有没有办法实现这一点,Bar
是所有Foo
的超类(接口)?
答案 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.Foo
与org.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
的引用的成本非常高,那么使用此策略可能是一个很好的折衷。