I have the interface
public interface UserResponseCallback {
void starting();
void success();
void error(String message);
void finish();
}
Is it possible to make the methods optional?
A non-abstract class must implement every abstract method it inherited from interfaces or parent classes. But you can use that to allow you to implement only certain required parts as long as you can live with the fact that you can no longer implement the interface at will.
You would create an abstract class that implements the optional part of the interface with empty default implementations like
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
}
You can now create subclasses that have to implement just the required parts while they still can implement the optional parts.
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);
}
}
This technique is for example used by AWT event callbacks e.g. MouseAdapter. It starts getting worth the extra effort once you use the callback multiple times since the optional part needs to be implemented only once instead of every time.
Your next option is top split the interface into two. Your conceptional problem is that your interface contains more than it should have, compare Interface Segregation Principle. You could split it either into two or more actually independent interfaces or you could extend a required base interface with optional extra features like
interface UserResponseCallbackBase {
// this is the only required part
void finish();
}
interface UserResponseCallbackFull extends UserResponseCallbackBase {
void starting();
void success();
void error(String message);
void finish();
}
To use that kind of hierarchical callback you would probably add some intelligence to whatever class manages the callbacks and let it check whether or not a callback wants a certain callback based on it's type.
For example like
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
}
}
}
That way you can freely choose which type of interface you want to implement and the calling code checks whether or not you want to get a callback. I.e. if you register(new UserResponseCallbackFull() {...})
you would be notified about starting()
, if you were to register(new UserResponseCallbackBase() {...})
you would not.
This technique is used in Android with ComponentCallbacks2
which you register via Context#registerComponentCallbacks(ComponentCallbacks)
- it takes both a "simple" ComponentCallbacks
and the extended version and checks what type you gave it.
No, that's not possible in Java.
Have a look at this question that comes to the same conclusion: Optional Methods in Java Interface