Inheritance in Java
Java does not support multiple inheritance, a deliberate choice to keep the language reasonably simple.
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, and it feels like a natural thing to ask for. Java does not allow it. A class in Java cannot be built directly from more than one parent. Understanding why that restriction exists is the first step toward understanding interfaces, which are Java's main answer to the problem.
Keep this question in mind as you read: if a class cannot have two parents, how does Java still give programmers a way to combine behavior from several sources? The rest of this article traces that answer step by step.
Why Java Left Multiple Inheritance Out
The restriction is a deliberate design decision. Java does not support multiple inheritance, and the designers chose this to keep the language reasonably simple. The reasoning is a trade-off, not a claim that multiple inheritance is useless. The designers judged that the benefits of multiple inheritance were not worth the extra complexity it would add to the language as a whole.
The diagram is an original illustration written to show how the ideas fit together; it is not taken from the source. It shows the kind of question the child class would have to answer. Java's designers did not want every program to carry the cost of resolving questions like this one, so the direct version of the idea was ruled out.
Interfaces as the Alternative Path
Java does not give up on the goals behind multiple inheritance. It provides a separate feature, called interfaces, that can accomplish many of the same goals. Because an interface is a different mechanism from class inheritance, it lets a program work toward those goals without bringing back the full complexity the designers wanted to avoid.
The goal is preserved while the mechanism is different. Multiple inheritance is the starting idea, Java rules out the direct version of it, and interfaces provide a path toward many of the same outcomes.
Following One Object Through Several Types
The scenario below is an original illustration. It is not taken from the source. It shows how one object can be treated as several different types at once: one type from its class, and additional types from each interface it implements. Read the code slowly and trace which methods belong to which source.
interface Swimmer {
void swim();
}
interface Flyer {
void fly();
}
class Animal {
void breathe() {
System.out.println("Breathing");
}
}
class Duck extends Animal implements Swimmer, Flyer {
public void swim() {
System.out.println("Paddling");
}
public void fly() {
System.out.println("Flapping");
}
}
public class Main {
public static void main(String[] args) {
Duck d = new Duck();
d.breathe();
d.swim();
d.fly();
Swimmer s = d;
s.swim();
Flyer f = d;
f.fly();
}
}- 1Swimmer and Flyer declare single methods with no bodies, which states what a class must provide.
- 2Animal supplies
breathe(), which Duck inherits through its one superclass. - 3Duck supplies the bodies for
swim()andfly(), which fulfil the two interface contracts. - 4In main,
d.breathe()comes from the superclass, whiled.swim()andd.fly()come from the interfaces. - 5Assigning the same object to a Swimmer variable lets the program treat it as a swimmer, and assigning it to a Flyer variable lets it treat the object as a flyer.
- Duck extends exactly one class, Animal
- Duck implements two interfaces, Swimmer and Flyer
- The variable s has type Swimmer but refers to the same Duck object
Breathing
Paddling
Flapping
Paddling
FlappingDuck d = new Duck();
Swimmer s = d;
// s can call swim()
// s cannot call fly()The same Duck object is viewed through the Swimmer type, which exposes only the swimming behavior.
Duck d = new Duck();
Flyer f = d;
// f can call fly()
// f cannot call swim()The same Duck object is viewed through the Flyer type, which exposes only the flying behavior. The object itself has not changed.
What do you think happens?
Can a Java class extend two classes at the same time, the way it can implement two interfaces?
Reveal answer
No, a class extends at most one class but can implement many interfaces.
Java does not support multiple inheritance, so a class cannot be built directly from more than one parent class. Interfaces are the separate mechanism that lets a class take on several types.
Functional Interfaces Within the Wider Idea
You have already met one special kind of interface. The source notes that functional interfaces were introduced in Section 4.5 in connection with lambda expressions. A functional interface specifies a single method. That single-method requirement is what makes it the right shape to pair with a lambda expression, which can stand in for that one method.
| Aspect | Interface in general | Functional interface |
|---|---|---|
| Number of methods | Can be much more complicated than a single method | Specifies a single method |
| Typical uses | Many uses, including important ones in Java's standard packages | Pairs with a lambda expression that stands in for the one method |
| Relationship | The broad category | A particular case within that category |
A functional interface is a specialized member of the wider interface category.
Every functional interface is an interface, but not every interface is functional. A functional interface is a particular case, not the whole story.
Where Programmers Meet Interfaces
The source states that interfaces have important uses in Java's standard packages. In practice, a programmer is likely to meet interfaces wherever code is written to accept a type rather than one specific class. When a method asks for an interface type, the caller is free to pass in any concrete implementation of that interface. The method does not need to know which class it receives, only that the object fulfils the interface's contract.
A library method might accept a parameter whose type is an interface. A programmer using that method can write their own class that implements the interface and pass an instance of it. The library code works with the interface, so the programmer's class fits in without the library having been written for that class in particular.
- Library method parameters that accept an interface type rather than one concrete class
- Framework callbacks where the framework expects an object that fulfils a contract
- Lambda expressions passed where a functional interface is expected
- Standard packages that define interfaces for shared behaviour
Mistakes When Reasoning About Interfaces
Common mistake Assuming Java lets a class extend two classes because it can implement two interfaces
What it looks likeWriting a class that extends both Animal and Plant
Why it failsJava does not support multiple inheritance, so a class cannot be built directly from more than one parent class.
Do this insteadUse one superclass for shared implementation and add interfaces for each additional type the class must fulfil.
Common mistake Thinking an interface must contain exactly one method
What it looks likeRefusing to write an interface with several methods because it is not a functional interface
Why it failsInterfaces can be much more complicated than a single method and have many uses.
Do this insteadReserve the single-method form for functional interfaces, which pair with lambda expressions, and use multi-method interfaces when the contract needs them.
Common mistake Treating a functional interface and the general idea of an interface as unrelated
Why it failsA functional interface is a particular case within the wider interface category.
Do this insteadThink of the functional interface as a specialized member of the broader category.
Practice: Sorting Out Parents and Contracts
A game program has a Hero class and needs heroes to be able to attack and to heal. Should attack and heal be provided by a second parent class, or by interfaces? Explain your choice using the reasoning from this article, and state what the Hero class can and cannot extend.
Hints
- Recall that Java does not support multiple inheritance.
- Consider which mechanism lets a class take on several types at once.
- Think about whether one class parent is still needed for shared code.
Key Takeaways
- Java does not support multiple inheritance, a deliberate choice made to keep the language reasonably simple.
- The designers judged that the benefits of multiple inheritance were not worth the extra complexity it would add.
- Interfaces are a separate Java mechanism that can accomplish many of the same goals as multiple inheritance without its full complexity.
- A functional interface specifies a single method and pairs with lambda expressions, but it is a particular case of the broader interface idea.
- Programmers meet interfaces wherever code accepts an interface type and lets the caller supply a concrete implementation.