Composition vs Inheritance in Object-Oriented Programming
A comprehensive explanation of composition vs inheritance, including code examples and best practices.
Object-oriented programming (OOP) is a programming paradigm that uses objects and classes to organize code. Two fundamental concepts in OOP are composition and inheritance. Inheritance is a mechanism that allows one class to inherit the properties and behavior of another class. Composition is a mechanism that allows one object to contain another object. The choice between inheritance and composition depends on the relationship between the classes and the complexity of the system.
Code Examples
This example demonstrates inheritance in Python. The Car and Truck classes inherit from the Vehicle class and add their own properties and methods.
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def honk(self):
print('Honk honk')
class Car(Vehicle):
def __init__(self, make, model, year, num_doors):
super().__init__(make, model, year)
self.num_doors = num_doors
def lock_doors(self):
print('Doors locked')
class Truck(Vehicle):
def __init__(self, make, model, year, bed_size):
super().__init__(make, model, year)
self.bed_size = bed_size
def lift_bed(self):
print('Bed lifted')This example demonstrates composition in Python. The Vehicle class contains an Engine object, which is a composition of the make, model, and start method.
class Engine:
def __init__(self, make, model):
self.make = make
self.model = model
def start(self):
print('Engine started')
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.engine = Engine(make, model)
def honk(self):
print('Honk honk')
class Car(Vehicle):
def __init__(self, make, model, year, num_doors):
super().__init__(make, model, year)
self.num_doors = num_doors
def lock_doors(self):
print('Doors locked')
class Truck(Vehicle):
def __init__(self, make, model, year, bed_size):
super().__init__(make, model, year)
self.bed_size = bed_size
def lift_bed(self):
print('Bed lifted')Common Pitfalls
- Tight coupling between classes can make it difficult to change one class without affecting others.
- Deep inheritance hierarchies can lead to tight coupling between classes and make it difficult to understand the relationships between classes.
Best Practices
- Use composition when there is a ‘has-a’ relationship between classes.
- Use inheritance when there is an ‘is-a’ relationship between classes.
- Avoid deep inheritance hierarchies and use interfaces and abstract classes to reduce coupling between classes.