The broader way of looking at composition and inheritance is, composition is a design technique to implement has-a
relationship whereas inheritance is a technique to implement is-a
relationship. Let's get into Object Orientation perspective to understand this in a better way.
When I say, Dog
is a Mammal
and Snake
is a Reptile
but both are Animals
, The design can be like, there should be a super class called Animal
and two child classes called Mammal
and Reptile
which Dog
and Snake
should be extending. Respective code is as below:
public abstract class Animal {
public abstract void move();
public abstract void sleep();
public abstract void reproduce();
}
Any animal can perform these three actions.
public abstract class Mammal extends Animal{
@Override
public void reproduce(){
System.out.println("Gives birth!!");
}
}
public abstract class Reptile extends Animal{
@Override
public void reproduce(){
System.out.println("Lays Eggs!!");
}
}
All Mammals/Reptile will perform this defined function in common way.
public class Dog extends Mammal{
@Override
public void move() {
System.out.println("Uses it's limbs");
}
@Override
public void sleep() {
System.out.println("Sleeps on it's tummy");
}
}
public class Snake extends Reptile{
@Override
public void move() {
System.out.println("Crawls");
}
@Override
public void sleep() {
System.out.println("");
}
}
As you can observe in this example, Dog
extends Mammal
and Snake
extends Reptile
. Hence at any given point of time, Dog
will always be a Mammal
and a Snake
will always be a Reptile
. Hence, this is-a relationship builds a strong bond between two entities. During the course of execution, as long as Dog
extends Mammal
, it cannot be a Reptile
or anything else.
Whereas coming back to has-a relationship (Composition), I can say that a Person
has-a Car
. I'm not specifying the type of the Car
that this person has. Let's get back to OO perspective to understand this better.
Consider this Person
class
public class Person {
private String name;
private String address;
private Car car;
public Person(String name, String address, Car car) {
super();
this.name = name;
this.address = address;
this.car = car;
}
}
It can be seen here that, a Person
has-a name, address and car.
The code for Car and related classes goes below:
public class Car {
//Car related methods
}
public class Ferrari extends Car{
//Ferrari specific methods, attributes
}
public class Bmw extends Car{
//BMW specific attributes, methods.
}
It can be seen that BMW
and Ferrari
are types of Car
.
Now coming back to the statement "Person has-a Car", the Car could be any Car. It could be a ferrari or BMW or anything else. This can be passed in during creation of Person
object.
Person john = new Person("John", "#81, 2nd Street,..", new Ferrari());
It can be seen that John takes in a Ferrari
Car
. Here John can take in any type of Car
being passed during object creation (dynamic nature). Hence that level of flexibility is provided by has-a (composition) relation.
I hope this clears your doubt.