Thursday, March 24, 2022

Composition

Composition is another popular concept in OOP that is again somewhat relevant to encapsulation. In simple words, composition means to include one or more objects inside an object to form a real-world object. A class that includes other class objects is called a composite class, and the classes whose objects are included in a composite class are known as component classes. In the following screenshot, we show an example of a composite class that has three component class objects, A, B, and C:

 

Composition is considered an alternative approach to inheritance. Both design approaches are meant to establish a relationship between objects. In the case of inheritance, the objects are tightly coupled because any changes in parent classes can break the code in child classes. On the other hand, the objects are loosely coupled in the case of composition, which facilitates changes in one class without breaking our code in another class. Because of the flexibility, the composition approach is quite popular, but this does not mean it is the right choice for every problem. How, then, can we determine which one to use for which problem? There is a rule of thumb for this. When we have an is a relationship between objects, inheritance is the right choice—for example, a car is a vehicle, and a cat is an animal. In the case of inheritance, a child class is an extension of a parent class, with additional functionality and the ability to reuse parent class functionality. If the relation between objects is that one object has another object, then it is better to use composition—for example, a car has a battery.

We will take our previous example of the Car class and the Engine class. In the example code for multiple inheritance, we implemented the Car class as a child of the Engine class, which is not really a good use case of inheritance. It's time to use composition by implementing the Car class with the Engine object inside the Car class. We can have another class for Seat and we can include it inside the Car class as well.

We will illustrate this concept further in the following example, in which we build a Car class by including Engine and Seat classes in it:

#composition1.py
class Seat:
def __init__(self, type):
self.i_type = type
def __str__(self):
return f"Seat type: {self.i_type}"
class Engine:
def __init__(self, size):
self.i_size = size
def __str__(self):
return f"Engine: {self.i_size}"
class Car:
def __init__(self, color, eng_size, seat_type): 

self.i_color = color
self.engine = Engine(eng_size)
self.seat = Seat(seat_type)
def print_me(self):
print(f"This car of color {self.i_color} with \
{self.engine} and {self.seat}")
if __name__ == "__main__":
car = Car ("blue", "2.5L", "leather" )
car.print_me()
print(car.engine)
print(car.seat)
print(car.i_color)
print(car.engine.i_size)
print(car.seat.i_type)

We can analyze this example code as follows:

1. We defined Engine and Seat classes with one attribute in each class: i_size for the Engine class and i_type for the Seat class.

2. Later, we defined a Car class by adding the i_color attribute, an Engine instance, and a Seat instance in it. The Engine and Seat instances were created at the time of creating a Car instance.

3. In this main program, we created an instance of Car and performed the following actions:
a) car.print_me: This accesses the print_me method on the Car instance.
b) print(car.engine): This executes the __str__ method of the Engine class.
c) print(car.seat): This executes the __str__ method of the Seat class.
d) print(car.i_color): This accesses the i_color attribute of the Car instance.
e) print(car.engine.i_size): This accesses the i_size attribute of the Engine instance inside the Car instance.
f) print(car.seat.i_type): This accesses the i_type attribute of the Seat instance inside the Car instance

The console output of this program is shown here:

This car of color blue with Engine: 2.5L and Seat type: leather
Engine: 2.5L
Seat type: leather
blue
2.5L
leather

In the next post, we will discuss duck typing, which is an alternative to polymorphism.

Share:

0 comments:

Post a Comment