Composition and Inheritance are OOP concepts that define different ways real-world things can be modelled in computer programs.
Inheritance is a mechanism where a new class is derived from an existing class. The new class, called the child or derived class, inherits properties and methods from the parent or base class. (it follows a is-a relationship)
class Animal: def speak(self): passclass Dog(Animal): def speak(self): return "Woof!"
Composition is a design principle where a class is composed of one or more objects of other classes. Instead of inheriting properties and methods, a class contains instances of other classes that it uses to access their functionality. (it follows a has-a relationship)
Both inheritance and composition have their uses, and the choice between them depends on the specific design requirements of your program.
Inheritance is useful for creating hierarchies of related classes, while composition is often more flexible and can lead to more modular designs.
Composition over inheritance
Composition is just software building on other software. Composition is much more modular and flexible as it’s much easier to change implementations.
Composition allows for behaviours to be altered at runtime by mixing-and-matching different objects whereas behaviour is fixed at compile time in case of inheritance.
Composition allows for more complex relationships to be defined whereas inheritance limits the extent of relationships that the objects can have.
One side effect is that composition produces looser coupling whereas inheritance leads to tighter coupling between parent and child.