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 } } } |
这样,您可以自由选择要实现的接口类型,并且调用代码检查您是否要获取回调。即如果您
在通过
不,这在Java中是不可能的。
看一下得出相同结论的这个问题:Java接口中的可选方法
没有。
使用虚拟实现,并在需要时覆盖。