关于android:可选的回调

Optional callbacks

本问题已经有最佳答案,请猛点这里访问。

我有界面

1
2
3
4
5
6
public interface UserResponseCallback {
    void starting();
    void success();
    void error(String message);
    void finish();
}

是否可以使方法可选?


非抽象类必须实现从接口或父类继承的每个抽象方法。但是,只要您能够忍受不能再随意实现接口这一事实,就可以使用它来仅实现某些必需的部分。

您将创建一个抽象类,该类使用空的默认实现来实现接口的可选部分

1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class UserResponseCallbackAdapter implements UserResponseCallback {

    @Override
    public void starting() { /* nothing */ }

    @Override
    public void success() { /* nothing */ }

    @Override
    public void error(String message) { /* nothing */ }

    // finish() intentionally left out
}

现在,您可以创建只需要实现必需部分的子类,而它们仍然可以实现可选部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User {
    private final UserResponseCallback callback = new UserResponseCallbackAdapter() {

        @Override
        public void finish() {
            // must be implemented because no empty default in adapter
        }

        @Override
        public void starting() {
            // can be implemented
        }
    };

    void foo() {
        // can be used like every other UserResponseCallback
        CallbackManager.register(callback);
    }
}

例如,AWT事件回调(例如,鼠标适配器。一旦您多次使用回调,它就值得您付出额外的精力,因为可选部分只需要实现一次,而不是每次都实现。

您的下一个选择是将接口顶部分为两个部分。您的概念性问题是,接口所包含的内容应大于其应有的数量,请比较接口隔离原理。您可以将其拆分为两个或多个实际上独立的接口,也可以使用可选的额外功能扩展所需的基本接口,例如

1
2
3
4
5
6
7
8
9
10
11
interface UserResponseCallbackBase {
    // this is the only required part
    void finish();
}

interface UserResponseCallbackFull extends UserResponseCallbackBase {
    void starting();
    void success();
    void error(String message);
    void finish();
}

要使用这种分层回调,您可能会在管理该回调的任何类中添加一些智能,然后让其根据其类型检查回调是否需要某个回调。

例如像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CallbackManager {
    private List<UserResponseCallbackBase> mCallbacks = new ArrayList<UserResponseCallbackBase>();
    public void register(UserResponseCallbackBase callback) {
        mCallbacks.add(callback);
    }

    public void notifyStarting() {
        for (UserResponseCallbackBase callback : mCallbacks) {
            // check if callback is of the extended type
            if (callback instanceof UserResponseCallbackFull) {
                ((UserResponseCallbackFull)callback).starting();
            } // else, client not interested in that type of callback
        }
    }
}

这样,您可以自由选择要实现的接口类型,并且调用代码检查您是否要获取回调。即如果您register(new UserResponseCallbackFull() {...}),您将收到有关starting()的通知,如果您是register(new UserResponseCallbackBase() {...}),则不会。

在通过Context#registerComponentCallbacks(ComponentCallbacks)注册的ComponentCallbacks2安卓系统中使用了此技术-它同时包含"简单" ComponentCallbacks和扩展版本,并检查您给它的类型。


不,这在Java中是不可能的。

看一下得出相同结论的这个问题:Java接口中的可选方法


没有。

使用虚拟实现,并在需要时覆盖。