Basic Java: What Interfaces really are?

As an assistant of a course in basic Java in my local university, I saw a common misunderstanding among students what interfaces really are. In this short article I’ll try to give students another point of view.

As we all know “an interface is a group of related methods with empty bodies”*. Consider the following example:

public interface CoffeeMaker {
    void grindCoffee();

    void brewCoffee();

    void cleanSelf();
}

public class DelonghiCoffeeMaker implements CoffeeMaker {
    ...
}

When asking a student why she made DelonghiCoffeeMaker implement the interface CoffeeMaker, the answer is always similar to “because I wanted to make sure it implements those methods”. The follow-up question “why specifically?” usually has no answer.

In other words students understand the semantics of the interface pretty good, but not its real purpose and intention.

As we all know Java is a single-inheritance language. As such it (arguably) misses some of the goodies of multi-inheritance languages such as C++ and Python . Interfaces are the way to overcome this (arguable) disadvantage.

Above else, interfaces denote Behavior. Type. Intention. By making a class implement an interface, you’re basically saying – “this class is a CoffeeMaker”. You can apply this behavior to any class, doesn’t matter if it already extends something else. And when you need a CoffeeMaker, you can use the interface to ask for it. Let’s look at another example:

void morningRoutine(DelonghiCoffeeMaker coffeeMaker) {
    coffeeMaker.grindCoffee();
    ...
}

The code looks fine, but we can do better. What happens if we get a better CoffeeMaker, for example a JuraCoffeeMaker. We can’t use it in our morningRoutime() method, as the latter is looking for a Delonghi one.

What our morningRoutine() really needs is just a CoffeeMaker. It’ll do it’s job with any brand, so why are we so strict in the method declaration? Here’s the better, more generalized version of it:

void morningRoutine(CoffeeMaker coffeeMaker) {
    coffeeMaker.grindCoffee();
    ...
}

As a rule of thumb try to always use the most abstract object you can get by with. Instead of asking for a specific implementation (DelonghiCoffeeMaker or JuraCoffeeMaker) it’s better to ask for the generic interface CoffeeMaker. This will make your code better and your programs easier to change in the future.

If you’re interested in reading more along these lines, I highly recommend “Item 19: Use interfaces only to define types” and “Item 52: Refer to objects by their interfaces” from the amazing book Effective Java by Joshua Bloch.

* https://docs.oracle.com/javase/tutorial/java/concepts/interface.html

Submit a Comment

Your email address will not be published. Required fields are marked *