Inheritence vs Composition
Published Sep 15 2023
It's worth noting that you can often achieve the best of both worlds by combining both composition and inheritance to maximize code reuse and design flexibility. The following examples not only illustrate the differences between the two but also highlight how they can be used together effectively.
Object Composition
Object Composition involves creating relationships between objects by having one object hold a reference to another. This is typically done through class properties.
class Engine {
public function start() {
echo "Engine started.\n";
}
}
class Car {
private $engine;
public function __construct() {
$this->engine = new Engine();
}
public function start() {
$this->engine->start();
}
}
$car = new Car();
$car->start();
In this example, the Car
class contains an instance of the Engine
class. When $car->start()
is called, it first calls $this->engine->start()
to start the engine, and then it continues to start the car. This is an example of object composition because Car
"has" an Engine
.
Class Inheritance
Class Inheritance involves creating new classes based on existing ones. The new class (subclass) inherits properties and methods from the existing class (superclass).
class Vehicle {
public function start() {
$this->startDesielEngine();
}
private function startDesielEngine() {
echo "Engine started.\n";
}
}
class Car extends Vehicle {
public function start() {
$this->startPetrolEngine();
}
private function startPetrolEngine() {
echo "Engine started.\n";
}
}
$car = new Car();
$car->start();
In this example, the Car
is a subclass of the Vehicle
class. They both have the start()
feature, but the implimentation of the feature needs to change for the inheriting subclass. In this example, the Car "has" a start feature. Even if both the Vehicle
and the Car
will share an interface, their implimentation of start()
can be different.
When to Use Object Composition and Class Inheritance:
Use Object Composition when:
- There is a clear "has" relationship between the classes (e.g., a Car has as Engine).
- You want to switch out components at runtime.
- You want to have fewer implementation dependencies.
- You want to keep your classes and class hierarchies small and manageable.
- You want to control access to the functionality of another class.
- You don't want to break encapsulation.
Use Class Inheritance when:
- There is a clear "is" relationship between the classes (e.g., a Car is a Vehicle).
- You want to provide a specific implementation of a more general class.
- You want to modify the behavior of an existing class by overriding certain operations.
- You don't mind changing every child class when the parent class changes.
There are clear trade-offs for both object composition and class inheritance. However, it's beneficial to use a combination of both object composition and class inheritance, depending on the specific needs of your application, as it allows for more flexible and maintainable code.