ProgrammingBackend Developer

What are composition and aggregation in object-oriented programming in Python, how do they differ, and where are they applied?

Pass interviews with Hintsage AI assistant

Answer.

Background:

Both terms — composition and aggregation — come from classical object-oriented design. They describe relationships between objects: "whole-part", but differ in the degree of interdependence of the objects.

Problem:

In large systems, code readability and extensibility are important. Composition and aggregation help establish clear dependencies between classes. It is important to understand the difference — otherwise, one can make the architecture too rigid or, conversely, vague.

Solution:

Composition is a strong "part-whole" relationship. When an object is contained only within another object and cannot exist outside it. In Python, such an object is usually created and managed within a "container" class.

Aggregation is a weaker relationship. The "part" object can exist separately from the "whole" object and be passed into it from the outside.

Code Example:

class Engine: def start(self): print("Engine started") class Car: # Composition: Engine is created inside Car def __init__(self): self.engine = Engine() def drive(self): self.engine.start() my_car = Car() my_car.drive() class Wheel: pass class Bicycle: # Aggregation: wheels are passed in from outside def __init__(self, wheels): self.wheels = wheels w1, w2 = Wheel(), Wheel() bike = Bicycle([w1, w2])

Key features:

  • Composition provides complete control over the lifecycle of the nested object.
  • Aggregation offers a more flexible architecture and weak links.
  • Through composition, it is easy to implement the "has-a" pattern, whereas aggregation facilitates shared use of objects.

Tricky Questions.

If the "container" object (for example, Car) is deleted, will the Engine object be deleted?

In composition, if no one references the "part" object anymore, it will be removed by the garbage collector. In aggregation, the "part" object can continue to exist (it may still be referenced by other objects).

Does Python have a special syntax for aggregation and composition, like in other languages?

In Python, there are no keywords indicating explicit composition/aggregation. It all depends on how the objects are created and their lifecycle.

Can composition be changed to aggregation and vice versa without rewriting the logic?

Not always. If the logic requires complete control and uniqueness of the "part" object, simply replacing composition with aggregation may lead to errors (for example, if the wheels for different bicycles become shared instances of the same class).

Typical Mistakes and Anti-Patterns

Pros:

  • Composition has clear control over the construction and destruction of objects.
  • Aggregation provides flexibility and reuse of objects. Cons:
  • Composition can lead to overly tight coupling.
  • Aggregation sometimes allows for logical errors due to "ownership separation" of objects.

Real-Life Example

Negative case: In a project, an external engine object was created for each car and passed into the car through aggregation. However, later the object references were mixed up, and engines were swapped between cars arbitrarily — which led to confusion and bugs.

Pros: the architecture seemed flexible. Cons: it was difficult to determine which engine belonged to which car.

Positive case: In another project, engines were created inside the Car class (composition); cars directly managed their engines, ensuring reliability.

Pros: no leaks and logical confusion. Cons: more code was needed to manage the lifecycle of each car and its components.