I am wondering how to convert overlapping type of inheritance to Java. I got abstract class Person, and 2 extending subclasses: Driver and Passenger. As you know, driver may also be a passenger. So the question is: what's the best way to implement overlapping in Java? I heard that the best way is to use the composition, but i don't know how to.
-
3If the driver is always a passenger, why don't you make driver a subclass of passenger? – RaminS Jun 13 '16 at 18:50
-
One solution dasblonkenlight approach. Other solution: Person having list of roles using composition. – Ravindra babu Jun 13 '16 at 18:58
-
related: http://stackoverflow.com/questions/56860/what-is-the-liskov-substitution-principle "if it looks lika a duck, quacks like a duck, but needs battieries - you probably have the wrong abstraction" – zapl Jun 13 '16 at 19:00
3 Answers
When a single class can play two roles in a system, an inheritance-based approach in Java is to define two interfaces, and have the class implement them:
interface Passenger {
... // Methods applicable to passengers
}
interface Driver {
... // Methods applicable to drivers
}
class Person implements Driver, Passenger {
... // A person can be a driver or a passenger
}
class Pet implements Passenger {
... // A pet can be only a passenger
}
You can use composition internally to implement the interfaces by forwarding method calls to private helper "passenger" and "driver" objects inside Person
.
In Java-8 you can place logic that is common to all implementing classes into default method implementations.

- 714,442
- 84
- 1,110
- 1,523
This is an extension of the answer provided by dasblinkenlight.
The solution is based on the component pattern described here by the Team Leader of the Tony Hawk dev team back in the '90s and it's often used in game development.
Disclaimer: I'm going to write the code without a Java compiler so please do tell me whether there are syntax errors.
Your abstract class Person
abstract class Person {
public String name;
}
This way we expose the behaviour of Driver
interface DriverInterface {
public void drive();
}
And here we export the behaviour of Passenger
interface PassengerInterface {
public void seat();
}
Here we put the actual logic of a Driver
class DriverComponent {
private Person person;
public DriverComponent(Person person) {
self.person = person;
}
public void drive() {
System.out.println("I'm" + person.name + " and I'm driving");
}
}
And here we put the logic of Passenger
class PassengerComponent {
private Person person;
public PassengerComponent(Person person) {
self.person = person;
}
public void drive() {
System.out.println("My name is " + person.name + " and I'm passenger");
}
}
Finally the Driver class
class Driver extends Person implements DriverInterface, PassengerInterface {
private DriverComponent driverComponent;
private PassengerComponent driverComponent;
private String name;
public Person(String name) {
driverComponent = DriverComponent(this);
passengerComponent = PassengerComponent(this);
}
public void drive() {
driverComponent.drive();
}
public void seat() {
passengerComponent.seat();
}
}
And the Passenger class
class Passenger extends Person implements Passenger {
private DriverComponent driverComponent;
private PassengerComponent driverComponent;
public String name;
public Passenger(String name) {
driverComponent = DriverComponent(this);
passengerComponent = PassengerComponent(this);
}
public void seat() {
passengerComponent.seat();
}
}
Wrap up
I really hope there are not syntax errors.
The power of this approach is that we do not replicate the logic of a Driver
or of a Passenger
because we write this code only once inside the related component.
The Component approach also allow us to easily create (and maintain) even combination of entity (like Driver, Passenger) and behaviour (DriverInterface
, PassengerInterface
) simply combining the related component.
It's the best alternative to multiple inheritance not supported by Java and it way better and clearer.

- 58,465
- 13
- 121
- 148
Similar to dasblinkenlight's answer, but I think more technically correct:
interface Person{}
interface Pet{}
interface HumanPassenger extends Person{}
interface PetPassenger extends Pet{}
interface Driver extends HumanPassenger{}
In this case Driver extends HumanPassenger and Person through HumanPassenger's ancestors. You can also do this explicitly via:
interface Driver extends HumanPassenger, Person{}
The reason that I say this is more technically correct is through the "is-a" relationship that descendant classes should have. For example, a HumanPassenger is a Person, a Person is not a HumanPassenger (a person could be anything that a person could be, not just a human passenger) in dasblinkenlight's answer, a person is a passenger, but what if a person is a pedestrian...
EDIT: Human Passenger, PetPassenger, and Driver, could all also be classes, I was just keeping it simple. example of Driver class:
class Driver extends HumanPassenger implements Person{}
or if HumanPassenger was an interface still:
class Driver implements HumanPassenger{}
or
class Driver implements HumanPassenger, Person{}
All would achieve the same things, though only the classes would be capable of instantiation of course.

- 443
- 1
- 4
- 12