Lesson 9
No Object is an Island
Chapter 2: Object interaction
Aggregation and composition
In the previous exercise, Car
and Driver
are quite loosely dependent. A Driver
instance will only have access to a Car
in the drive()
method (passed as an input argument).
But perhaps we might also want Driver
to actually have some ownership towards the Car
instance? Since he will be driving the car a lot?
In object-oriented programming, such “has-a” relationships are known as aggregation or composition. Some people also call this a “whole/part” relationship. So you can think of an object as being “part of” another object.
For example, your Hero
might have a Hand
and a Weapon
, a Book
might have an Author
, a Car
might have an Engine
and a Wheel
, a Webpage
might have a Button
and a SearchBar
etc.
Naturally, the object ‘part’ will be an instance attribute/variable of the ‘whole’ object, so you would usually initialise them in the constructor of the ‘whole’ object.
There are two ways to implement composition/aggregation. You can pass in an existing instance as an input argument to the constructor (weapon
in the code below), or you can construct a new object directly inside the constructor (Head()
in the code below).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Unlike previously with enemy
, I used the .is_charged()
method of self.weapon
in Line 14 without passing it as an input argument to cast_spell()
, since Hero
actually owns a weapon
. In a sense, you can consider aggregation/composition to be stronger form of dependency compared to just passing the object as an input argument to a method. Think of your hero owning a weapon vs. picking up a weapon when needed.
A Head
instance itself can also have more ‘parts’ (Eye
, Nose
, Mouth
), and each can have their own ‘parts’ (an Eye
might have an Eyebrow
, Pupil
, Iris
etc. So you end up with a hierarchy of ‘parts’!
As you can see, composition/aggregation can be quite a powerful abstraction!