'Is it OK to add default implementations to methods of an interface which represents a listener?

There is a certain library I use in my project. This library has an interface which has about 15 methods.

The purpose of this interface is to make it possible to subscribe for some events that are generated in the library. A listener class in application can implement this interface and register itself as a listener in the library to receive events.

All the methods in this interface are actually events. There can be listeners who only need to receive only one or two events from many events in the interface. Even though a listener is only interested in few events, listener has to implement all the methods when extending the interface.

So I asked the developer of this library to add empty default implementations to the methods in the interface.

But the library developer refuses to add default implementations, stating that it would violate java best practices and using default implementations in interface methods go against the purpose of interfaces.

But, as I can understand, a method in this interface does not specify some action which an implementer of this interface should be capable of. A method in this interface rather defines an event which an implementer may be interested in. So I can't see a clear reason for not adding default implementations.

So, is adding default implementations to this interface break the java best practices?



Solution 1:[1]

But the library developer refuses to add default implementations, stating that it would violate java best practices and using default implementations in interface methods go against the purpose of interfaces.

This argument was valid until default interface methods were introduced. Now your colleague would have to argue that the JLS of Java 8 perverted interfaces and the JDK now contains classes which go against the purpose of interfaces. Still this is a viable extreme standpoint but fruitless.

You simply can avoid the discussion by deriving an own interface from the library interface and providing default empty implementations for all inherited methods.

public interface MyInterface extends LibraryInterface {
    @Override default public void event1() {
    }

    ...
}

Or you both can review the following design which seems dubious to me and which led to your discussion about default method in interfaces:

Even though a listener is only interested in few events, listener has to implement all the methods when extending the interface.

A solution could be to simply split up the big interface in many smaller ones.

Solution 2:[2]

The library developer is wrong about this (I even dare to omit IMHO).

One of the reasons that many helper (both abstract and concrete) classes in Java have been introduced in the past is exactly the absence of features like default interface methods (for example the adapter classes in Swing which very much resemble the concerns you are asking about).

If not misused, multiple inheritance is desirable in some situations and, as we all know, by extending a 'helper' class in Java we are loosing the ability to inherit from anything else.

Actually, this is mentioned in the official Java tutorial, section "Abstract Classes Compared to Interfaces":

Consider using interfaces if any of these statements apply to your situation:

  • You expect that unrelated classes would implement your interface. For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.
  • You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.
  • You want to take advantage of multiple inheritance of type.

The second and the third point are the perfect match for your use case I think.

Solution 3:[3]

Since default methods enable us to add new functionalities to interfaces without breaking the classes that implement that interface so its definitely not a good practice because it combines the virtue of interfaces and abstract classes, but since that isn't an option I would strongly suggest that you provide your own skeletal implementation class, as this 'methodology' is used all over the Collections Framework in java, and that's just my humble opinion.

Solution 4:[4]

In short: Default methods should not be needed. The only reason they where introduced and are used within the JDK is to stay downwards compatible, and this should be the only reason to use it in your library. While default interface methods do NOT break the SOLID desin principles, there usage in your code are an indicator that you broke SOLID somewhere else.

In long:

I do not share the view of Dragan Bozanovic.

You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.

This does IMHO not speak for interface default methods. Specifying behavior is not the same as implementing a behavior. And the second part of the sentence even says "you are not concerned about who implements the behavior". A default method would implement it by its own. It would be very much concerned about who implements it then. Still, you do not concern about who OVERRIDES it.

You want to take advantage of multiple inheritance of type.

Java knows about three inheritance mechanisms: Inheritance of state, inheritance of implementation and inheritance of type. All three of them are inheritance. This quote is talking about inheritance of type. Interfaces without default methods use inheritance of type. Defaults methods in interfaces are inherited by implementation.

I share the view of oracle

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

The key part here is "ensure binary compatibility". I.e: It is bad design to use default for freshly created interface, but OKish to add them to legacy interface to not break the code of your clients.

With other words: Whenever you feel the need to use default methods you are probably breaking the SOLID principle somewhere in your architecture. Eg, the library you are talking about is breaking the Interface Segregation Principle.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 wero
Solution 2 Dragan Bozanovic
Solution 3 QuakeCore
Solution 4 user2542461