在我正在使用的第三方库中,有以下一些层次结构:
public abstract class Foo
{
// Class is public in the Java sense and public in the library's API
}
public class FooImpl extends Foo
{
// While this class is public in the Java sense, it is
// NOT part of the public API and is not even documented
// Library functions that hand back instances of this class
// hand them back as type Foo
}
库中的各种方法对Foo类型的东西进行操作. Foo文档称用户可以扩展Foo以进行具体实现,并且(显然)库提供了具体的实现.
我很满意图书馆提供的实现,除了一个方法,我想改变一下它的行为.但我提供的等级制度让我感到沮丧.
如果Foo是一个接口(它不是!),我只是这样做:
public FooWrapper implements Foo
{
private Foo wrappedImpl;
public FooWrapper(Foo toBeWrapped) {
wrappedImpl = toBeWrapped;
}
List<Whatever> methodIWantToTweak() {
List<Whatever> list = wrappedImpl.methodIWantToTweak();
do_something_to_list(list);
return list;
}
Something methodThatsOk() {
return wrappedImpl.methodThatsOk();
}
// similar delegations for remaining methods
}
但是因为它不是一个界面我不能这样做,或者至少不能干净利落地做到这一点.
我能想到的唯一事情是:
1)扩展API非公共类FooImpl并覆盖我想要调整的方法.
2)做类似的事情:
public class FooWrapper extends Foo
{
private Foo wrappedImpl;
public FooWrapper(Foo toBeWrapped) {
super();
wrappedImpl = toBeWrapped;
}
List<Whatever> methodIWantToTweak() {
List<Whatever> list = wrappedImpl.methodIWantToTweak();
do_something_to_list(list);
return list;
}
Something methodThatsOk() {
return wrappedImpl.methodThatsOk();
}
// Override all non-final public, protected, and package-local
// methods and delegate them to wrappedImpl
}
这两种方法都闻起来像我.第一个问题是它依赖于一个它不应该知道的类,以及哪个类可以在库的未来版本中更改/消失/重命名.第二个问题是FooWrapper的超类片段实际上没有被使用,并且不可能覆盖Foo的任何最终或私有方法(这将导致问题,因为在那些情况下,一个人无法委托给wrappedImpl).
我想我必须采用第一种方法,因为至少它会给出正确的行为,而第二种可能会以潜在的邪恶,微妙的方式被打破,这取决于Foo的内部细节.
我只是运气不好吗?我还有哪些其他方法/想法?
解决方法:
我想不出任何其他不会更臭的方法! (反思会起作用,但在这种情况下,它会比你试图避免的问题更糟糕.)
我认为第二种方法是最好的.如果Foo抽象类被设计为公共类,那么它不应该有令人讨厌的内部细节可能会让你失望.如果是这样,他们的设计就错了.
请注意,因为您要为“真正的”Foo实例创建包装类:
>您可以忽略抽象类为“真正的”Foo子类提供的大多数功能.
>您可以忽略由Foo级属性表示的任何状态.
>您可以在API中存根不需要在应用程序中使用的方法;例如编码它们以抛出UnsupportedOperationException.
所有这些都有助于降低问题的复杂性.