2

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?

TMH
  • 6,096
  • 7
  • 51
  • 88

3 Answers3

6

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.

zapl
  • 63,179
  • 10
  • 123
  • 154
  • Thanks for the in-depth answer :). I'll use the class example you put, that looks like it will do the job nicely :). – TMH Feb 18 '14 at 13:17
  • A brilliant answer + references to implementations...+1 ! – FD_ Feb 18 '14 at 13:28
  • Why do you repeat `void finish();` in the full interface? – Tim Sep 14 '16 at 14:55
  • @TimCastelijns For clarity. Methods are still there if you don't repeat them but I like seeing the entire interface at a glance. – zapl Sep 14 '16 at 15:42
4

No, that's not possible in Java.

Have a look at this question that comes to the same conclusion: Optional Methods in Java Interface

Community
  • 1
  • 1
FD_
  • 12,947
  • 4
  • 35
  • 62
1

No.

Use a dummy implementation and override if needed.

Thomas R.
  • 7,988
  • 3
  • 30
  • 39