Concepts / Defining and Implementing Interfaces

Defining and Implementing Interfaces

Java does not support multiple inheritance, a deliberate choice to keep the language reasonably simple.

  • Programming

A Class With Two Parents

Imagine you want one class to pick up behavior from two different parent classes at the same time. Many programmers expect a language to let you do this. Java does not. A class in Java cannot be built directly from more than one parent. This article explains why that restriction exists, and how Java still lets a class take on several sources of behavior through a separate feature called interfaces.

What do you think happens?

Can a single Java class extend two other classes directly?

  • Yes, if the two parents have different methods

  • No, a class can extend only one other class

Reveal answer
Answer:

No, a class can extend only one other class

Java does not support multiple inheritance. A class in Java cannot be built directly from more than one parent. Interfaces are the mechanism Java provides to reach many of the same goals.

Why Java Left Out Multiple Inheritance

The restriction is a deliberate design choice. The designers of Java wanted to keep the language reasonably simple. They judged that the benefits of multiple inheritance were not worth the extra complexity it would add to the language as a whole. The source is careful to say this is a trade-off, not a claim that multiple inheritance is useless. A feature that is useful in some situations was left out because of what it would cost everywhere else.

Key point

Java's refusal of multiple inheritance is a judgment about trade-offs. The goal behind the feature is still valuable, which is why Java provides another route to it.

Keeping the Goals Without the Mechanism

Java does not give up on the goals behind multiple inheritance. Instead it provides a separate feature, interfaces, that can accomplish many of the same goals. Because an interface is a different mechanism from class inheritance, a program can work toward those goals without bringing back the full complexity the designers wanted to avoid. The key point is that the goal is preserved while the mechanism is different.

It helps to think of the two ideas as a starting point and a path. Multiple inheritance is the starting idea. Java rules out the direct version of it, but interfaces offer a route toward many of the same outcomes.

Tracing an Interface Gap Being Filled

An interface lists method headers without giving their bodies. That leaves a gap, and something has to fill it. The class that fills the gap is the one that implements the interface. The example below is an original illustration written for this article, not the source's own code. It shows a Strokeable interface with one method header and a Line class that fills that gap.

java
java
Notes on the code
  • The class header names the interface it promises to satisfy.
  • The stroke() method is the method the interface requires, and the class supplies its body.
Output
Drawing a line of length 5

What Happens When the Method Is Missing

What do you think happens?

Imagine a version of Line where stroke() is left out entirely. Would the class still count as a concrete class that implements Strokeable?

  • Yes, the method is optional

  • No, the class does not meet the interface's requirements

Reveal answer
Answer:

No, the class does not meet the interface's requirements

The source is explicit that both the implements clause and the method implementations are required. Omitting the method means the class does not meet the interface's requirements. The method is a requirement, not an option.

Before
public class Line implements Strokeable {
    private int length;
}

The header promises Strokeable, but the stroke() method is missing, so the class does not meet the interface.

After
public class Line implements Strokeable {
    private int length;

    @Override
    public void stroke() {
        System.out.println("Drawing a line");
    }
}

The header and the required method are both present, so the class satisfies the interface.

The Two Requirements a Class Must Meet

The source is explicit that writing the methods is not enough by itself. A class has to meet two separate conditions, and each condition does a different job. The two conditions are examined one at a time below.

Writing the Class Header

One Superclass, Many Interfaces

A class can extend one other class and implement any number of interfaces. The source gives the header FilledCircle extends Circle implements Strokeable, Fillable as a valid example. The diagram below shows which parts of the class come from which source. The superclass supplies one line of inheritance, and each interface contributes its own required methods.

FilledCirclethe class being writtenCirclesingle superclassStrokeableinterfaceFillableinterfaceextendsimplementsimplements
Which parts of a class come from its single superclass, and which come from each interface it implements, and how do they combine in one class?

Locating the Source of a Failure

When a class fails to compile against an interface, the fastest way to find the cause is to check the two requirements in order. The flowchart below follows that order. Start at the class header, then check the method definitions. The first check that fails tells you where to look.

Header usesimplements?Every method defined?Class satisfiesinterfaceFix the classheaderAdd the missingmethodnoyesnoyes
When a class fails to compile against an interface, which check failed first, and where in the class should I look for the cause?

Mistakes Beginners Make

  • Common mistake

    Assuming a class can extend two classes because it can implement two interfaces

    What it looks like

    class FilledCircle extends Circle, Shape

    Why it fails

    Extending is limited to one other class. Implementing is not limited in the same way.

    Do this instead

    Extend exactly one class and list the interfaces after implements.

  • Common mistake

    Writing the implements clause but leaving out the method

    Why it fails

    The source states that omitting either requirement means the class does not meet the interface.

    Do this instead

    Define every instance method the interface declares.

  • Common mistake

    Writing the method without naming the interface in the header

    Why it fails

    The header is the promise. Without implements, the class does not state that it satisfies the interface.

    Do this instead

    Add implements followed by the interface name to the class header.

Where Programmers Meet Interfaces

Interfaces appear in many places beyond code you write yourself. The source notes that interfaces can be much more complicated than a single method and that they have many uses, including important ones in Java's standard packages. You will often meet interfaces in library code and frameworks, where a class you did not write must implement a set of methods so that other code can call it.

Functional Interfaces as a Special Case

A functional interface specifies a single method. The source notes that you have already met one special kind of interface: functional interfaces were introduced earlier in connection with lambda expressions. The single-method requirement is what makes a functional interface the right shape to pair with a lambda, since a lambda expression can stand in for that one method.

Key point

A functional interface is a particular case, not the whole story. Every functional interface is an interface, but not every interface is functional. General interfaces can declare several methods.

Key Takeaways

  • Java does not support multiple inheritance, a deliberate trade-off made to keep the language reasonably simple.
  • Interfaces let Java pursue many of the same goals as multiple inheritance through a different mechanism.
  • A class implements an interface by using implements in its header and by defining every instance method the interface declares; both requirements are needed.
  • A class can extend one other class and implement any number of interfaces, and a failure can be traced by checking the header first and then the methods.
  • A functional interface, with its single method, is one special case of the broader idea of an interface.