This blog post aims to explain how we can use intersection types in Java when we expect an object that implements different interfaces.
Interface Segregation Principle
The Interface Segregation Principle (ISP) stipulates that interfaces should contain the least amount of methods as possible. In other terms, a client of an interface should use all the methods of this interface.
For instance, let’s take this
1 2 3 4 5 6 7 8 9
As a client of this interface, it is highly unlikely that I need all methods. I may want to just read the file and, in that case, I certainely don’t want to be able to delete it. If I just want to delete the file, I probably don’t want to read all its lines.
In order to avoid that, it is a good idea to split this interface in 3 seperate ones:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Now, a client can just require the interface it needs and ignore the rest.
Writing tiny interfaces is good to enforce ISP and lower the coupling of the code. However, what happens when a client wants to read a file and write at the same time?
The first two snippets won’t compile because one of the interface is not implemented:
1 2 3 4 5 6 7 8 9
As an alternative, it is possible to pass an instance of
LocalFile but it introduces a high coupling between the method and the LocalFile concrete class, defeating the whole purpose of interfaces entirely.
1 2 3 4 5
Since Java 1.5, and the introduction of generics, a feature, known as Intersection Types, allows to combine interfaces in this kind of situation.
Intersection Types to the Rescue
The following code uses intersection types to solve the issue of needing an object that implements several interfaces:
1 2 3 4
& symbol means that the method expects a type
T that implements both the
The intersection types is a feature that is not widely used in Java. However, it is very powerful as it allows to write very tiny interfaces and combine them on demand. From now on, there is no excuse to write big fat interfaces that have dozens of totally unrelated methods!