java – 使用第三方抽象类,就好像它是一个接口?

在我正在使用的第三方库中,有以下一些层次结构:

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.

所有这些都有助于降低问题的复杂性.

上一篇:传递接口作为函数参数(PHP)?


下一篇:php – TCPDF:如何以正确的方式设置FONT SIZE