Inheritance
Inheritance is a mechanism in object-oriented programming (OOP) where a new class (the child class or subclass) inherits properties and methods from an existing class (the parent class or superclass).
"Is-a" relationship: Inheritance models an "is-a" relationship. For example, a Dog is an Animal. The Dog class would inherit general characteristics and behaviors from the Animal class and can also have its own specific attributes and methods (like bark()).
Code Reusability: Inheritance promotes code reusability. Common functionalities can be defined in the parent class and reused by multiple child classes, reducing code duplication.
Extensibility: Child classes can extend or override the functionality inherited from the parent class to suit their specific needs.
Example in Python:
Python
class Animal:
def init(self, name):
self.name = name
def speak(self):
print("Generic animal sound")
class Dog(Animal):
def speak(self): # Overrides the parent's speak method
print("Woof!")
class Cat(Animal):
def speak(self): # Overrides the parent's speak method
print("Meow!")
dog = Dog("Buddy")
cat = Cat("Whiskers")
dog.speak() # Output: Woof!
cat.speak() # Output: Meow!
print(dog.name) # Output: Buddy (inherited from Animal)
Composition
Composition is a design principle in OOP where a class contains objects of other classes. Instead of inheriting behavior, the class achieves its functionality by delegating tasks to its constituent objects.
"Has-a" relationship: Composition models a "has-a" relationship. For example, a Car has an Engine and Wheels. The Car class would contain instances of the Engine and Wheel classes and use their functionalities.
Flexibility: Composition offers more flexibility than inheritance. You can easily change the behavior of a class at runtime by replacing its component objects.
Loose Coupling: Composition leads to looser coupling between classes. Changes in one component class are less likely to affect the classes that use it (as long as the component's interface remains the same).
Example in Python:
Python
class Engine:
def start(self):
print("Engine started")
def stop(self):
print("Engine stopped")
class Wheels:
def rotate(self):
print("Wheels are rotating")
class Car:
def init(self):
self.engine = Engine()
self.wheels = Wheels()
def drive(self):
self.engine.start()
self.wheels.rotate()
print("Car is moving")
def park(self):
self.engine.stop()
print("Car parked")
my_car = Car()
my_car.drive()
my_car.park()
How Inheritance and Composition are Related
Both inheritance and composition are mechanisms for achieving code reuse and building complex objects in OOP. However, they differ in their approach and the type of relationship they model:
Inheritance focuses on creating a hierarchy of classes where subclasses inherit and extend the behavior of their superclasses ("is-a").
Composition focuses on building objects by combining instances of other classes, leveraging their functionalities ("has-a").
In many situations, you might need to choose between inheritance and composition. The principle "favor composition over inheritance" is often recommended because composition tends to lead to more flexible, maintainable, and less coupled code.
However, inheritance is still valuable when there is a clear "is-a" relationship and you want to reuse and extend a well-defined base class. Sometimes, a combination of both inheritance and composition can be used effectively to model complex systems. For instance, a base class might define a general structure (inheritance), while its instances contain specialized component objects (composition) to perform specific tasks.