可以从我的代码中重构另一个包中的 Java 接口吗?
我在我的 Java 项目中使用(开源)API 并从中引用接口。一个接口 (Foo
) 在 API 和使用它的项目中广泛使用。对于我的项目,我想使用一个仅公开 Foo
所执行的方法的子集的接口,这样 Foo
将从我的新接口继承方法(<代码>条)。我根本不想改变 Foo
的界面;相反,我希望能够编写实现 Bar
的类,然后将它们与实现 Foo
的类一起操作,就好像它们都是 Bar< /代码>。
由于 API 位于不同的包中,是否有任何方法可以实现此目的,使 Bar
成为所有 Foo
的超类(接口)?
I'm using an (open-source) API in my Java project and referencing interfaces from it. One interface (Foo
) is used extensively both in the API and in projects that use it. For my project, I'd like to use an interface which only exposes a subset of the methods that Foo
does, such that Foo
would inherit methods from my new interface (Bar
). I don't want to change the interface of Foo
at all; rather, I'd like to be able to write classes which implement Bar
, and then manipulate those along with classes which implement Foo
as if they are all Bar
.
Since the API is in a different package, is there any way to accomplish this such that Bar
is a superclass (interface) of all Foo
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以创建一个实现 Foo 的抽象 Bar。您将放弃两者共享的方法并实现 Bar 不共享的方法,这样它们就会抛出
UnsupportedOperationException
之类的异常。但是你不能像操作 Bar 一样操作 Foo;恰恰相反。您无法按照您提出的方式满足里氏替换原则。
You can create an abstract Bar that implements Foo. You'll leave off the methods shared by the two and implement the methods that Bar does not share so they throw an exception like
UnsupportedOperationException
.But you can't manipulate Foo as if it were Bar; it's the other way 'round. You can't satisfy the Liskov Substitution Principle the way you're proposing.
您可能需要使用 Aspect 来实现这一点。看起来 AspectJ 有一个 @DeclareParents 可能会做你想做的事。
You're probably going to need to use an Aspect to make this happen. It looks like AspectJ has a @DeclareParents that might do what you want.
您可以使用 适配器模式 来完成此操作:
You could use the Adapter Pattern to accomplish this:
因为 Java 有名义类型,所以
org.theirs.Foo
与org.yours.Foo
没有任何关系,即使它们具有完全相同的方法签名,我不认为 Java 中的继承可以做到这一点。即使使用泛型,据我所知,也无法说“此方法采用Bar
的实例”。相反,我认为您想为库的
Foo
适配器接口 >,使用您自己的(即FooAdapter
,具有与Foo
完全相同的签名)并扩展Bar
。然后可以从FooAdapter
中提取Bar
中所需的方法。不幸的是,您的代码必须进行修改,以便您之前引用其Foo
的任何地方,您可以改为引用:Bar
(如果调用的唯一方法) 需要在接口FooAdapter
中定义这些方法Foo
中定义的方法而不是Bar
中定义的方法,则。这种方法虽然干净,并且很好地分离了关注点,但恐怕实施起来会很痛苦且乏味。
以下代码片段显示了其工作原理的示例:
第 3 方库
您的代码
您可以从此示例中看到,方法
doSomethingExtra()
无法从您的代码访问,因为接口 < code>Bar 没有指定它。其他建议
请注意,您可能可以在类重写方面使用一些有用的技巧,例如使用 AspectJ。我假设您更愿意在纯 Java 编译时获得您想要的效果。
另一个建议是实现
Bar
,它会为不需要的Foo
方法抛出UnsupportedOperationException
。尽管在主要的 Java 库中已有这样的先例(例如 JDK 中的UnmodifyingList
),但我一般建议不要采用这种做法。但是,如果用新的FooAdapter
替换对其Foo
的引用的成本相当高,那么使用此策略可能是一个不错的权衡。Because Java has nominal typing, such that
org.theirs.Foo
is in no way related toorg.yours.Foo
, even if they have the exact same method signatures, I don't think this is possible to do with inheritance in Java. Even with generics, AFAIK there is no way to say, "this method takes an instance ofBar<T extends Foo OR Bar>
".Instead, I think you want to use an Adapter interface for the library's
Foo
, with your own (i.e. aFooAdapter
, having the exact same signatures asFoo
) and have this extendBar
. The methods you want inBar
could then be extracted fromFooAdapter
. Unfortunately your code would have to be modified so that everywhere you previously referenced theirFoo
, you would instead reference either:Bar
if the only methods called are those you would define in your interfaceFooAdapter
if methods defined inFoo
but NOT inBar
are called.This method, although clean, and a good separation of concerns, can be painful and tedious to implement, I'm afraid.
An example of how this would work is shown in the following code snippets:
3rd Party Library
Your code
You can see from this example that the method
doSomethingExtra()
is not accessible from your code, since the interfaceBar
does not specify it.Other Suggestions
Note there may be useful tricks you could do with class rewriting, such as with AspectJ. I'm assuming you'd rather have the effect you desire at compile-time, in pure Java.
Another suggestion is to have an implementation of
Bar
which throwsUnsupportedOperationException
for the methods ofFoo
that you don't need. Although there is a precedent for this in major Java libraries (e.g.UnmodifiableList
in the JDK) I would recommend against this practice in general. However, if the cost of replacing references to theirFoo
with your newFooAdapter
is quite high, it may be a good trade off to use this strategy.