Learn to build complex objects by combining smaller, simpler objects.
Imagine building a smartphone. Would you try to 'evolve' a screen out of a battery, or would you assemble separate, specialized parts into a single frame? In software, the best systems aren't born; they are assembled.
In Object-Oriented Programming (OOP), we model the world. Inheritance represents an 'is-a' relationship. For example, a Car is a Vehicle. It inherits all traits of a vehicle. However, Composition represents a 'has-a' relationship. A Car has an Engine, has Wheels, and has a Transmission. Instead of gaining features from a parent, a class gains features by containing other objects as its building blocks. This 'has-a' approach is often more powerful because it allows us to build complex machines from simple, swappable parts without the rigid constraints of a family tree.
Quick Check
If a 'Library' class contains a list of 'Book' objects, is this an 'is-a' or a 'has-a' relationship?
Answer
It is a 'has-a' relationship (Composition), because a Library is not a type of Book; it contains Books.
To implement composition, we define a class where one or more attributes are instances of other classes. Think of it like a Russian nesting doll, but each doll does something different. When the 'outer' object is created, it can also initialize its 'inner' objects. This keeps code encapsulated: the Car class doesn't need to know how the Engine works internally; it only needs to know how to call the engine's `start()` method. This separation of concerns makes your code easier to debug and maintain.
1. Create a `CPU` class with a `speed` attribute. 2. Create a `RAM` class with a `capacity` attribute. 3. Create a `Computer` class. 4. Inside the `Computer` constructor, initialize `self.processor = CPU(3.5)` and `self.memory = RAM(16)`. 5. Now, the `Computer` object 'has-a' `CPU` and 'has-a' `RAM`.
Why choose composition over inheritance? Inheritance creates a tight coupling. If you change the parent class, every child class might break—this is known as the Fragile Base Class problem. Composition offers loose coupling. You can swap components at runtime. If your `Robot` class has a `Tool` attribute, you can change that tool from a `Drill` to a `Screwdriver` instantly. In math terms, if is a composite object of and , the complexity of is the sum of its parts, but its dependency is limited to the interfaces of and .
1. Define a `Hero` class. 2. Define a `Sword` class and a `Bow` class, both having a `use()` method. 3. Give the `Hero` an attribute called `weapon`. 4. At the start of the game, set `hero.weapon = Sword()`. 5. When the player finds a chest, simply update the reference: `hero.weapon = Bow()`. The `Hero` class code never has to change to accommodate a new weapon type.
Quick Check
What is the primary risk of using deep inheritance hierarchies compared to composition?
Answer
Tight coupling (or the Fragile Base Class problem), where changes to a parent class can unexpectedly break many descendant classes.
Experienced developers follow the principle: 'Favor composition over inheritance.' This doesn't mean inheritance is bad, but composition is often more robust. It allows for polymorphism without the baggage of a hierarchy. By using composition, you can create a `SmartHome` object that contains an array of `Device` objects. Whether the device is a `Light`, a `Thermostat`, or a `SecurityCamera`, the `SmartHome` treats them all as components. This makes your system infinitely expandable.
1. Design a `RemoteControl` class that has a list called `connected_devices`. 2. Create different classes for `TV`, `Stereo`, and `AirConditioner`, each with a `power_on()` method. 3. Use a loop in the `RemoteControl` to call `device.power_on()` for every object in its list. 4. This demonstrates how composition allows one object to manage a diverse group of other objects through a unified interface.
Which relationship is an example of composition?
What is a major benefit of using Composition over Inheritance?
In composition, the 'outer' class must know the internal private code of the 'inner' component class to use it.
Review Tomorrow
In 24 hours, try to explain the difference between 'is-a' and 'has-a' to a friend using a Car or a House as an example.
Practice Activity
Try this on your own: Create a 'Character' class for a game that has 'Stats', 'Inventory', and 'Equipment' as separate component classes.