Composition And Aggregation
Composition And Aggregation
In OOP programming, one hears that ‘Composition is better than Inheritance‘. Why? And is it always true? To answer these questions, we will first explore how Composition, and a closely related concept, Aggregation, work.
Let’s first consider what Composition and Aggregation have in common: Both are parent-child relationships. However, unlike with Inheritance, a child is not a specialised version of the parent. With Aggregation and Composition, a child is part of a parent. Several different child-parts will make up the parent. The parent is composed of its children.
An example is in order.
With Inheritance, the parent is, say, the Engine
class. The child or subclass versions will be specialised versions of Engine
: PetrolEngine
, ElectricEngine
, NuclearEngine
, and so on.
Let’s carry on with the Engine
example for Aggregation and Composition. An ElectricEngine
class might be made up of Magnets
, Wire
, Brushes
, etc.. And PetrolEngine
will be composed of Pistons
, FuelInjection
, SparkPlugs
and other parts.
And the difference between Aggregation and Composition?
Use Composition to model scenarios where the component parts do not exist independently from the parent. Pistons
are not much use other than in a PetrolEngine
. Therefore we should prefer Composition to model our PetrolEngine
in OO code.
Aggregation is a looser relationship between parent and children: Children can exist outside of the parent. For example, Student
(child) exists independently from Course
(parent).
How might we model these differences in code?
Aggregation:
public class Course { private IList<Student> Students { get; } = new List<Student>(); public void Add(Student student) { Students.Add(student); } }
With Aggregation, the Student
class may exist independently from the Course
. Therefore it is acceptable for the Student
instance to be created outside of the Course
and then passed into it via the Add()
method.
Composition:
public class PetrolEngine { private IList<Piston> Pistons { get; } = new List<Piston>(); public Course(int numberOfPistons = 4) { for (var i = 0; i < numberOfPistons; i++) Pistons.Add(new Piston()); } }
For Composition, Pistons
only make sense within the PetrolEngine
. PetrolEngine
internally instantiates the required number of Pistons
. Or in other words, if Pistons
do not make sense by themselves, then they should not be instantiated and passed into PetrolEngine
. Doing so would imply that we can create and use the Piston
class outside of PetrolEngine
.
Question: Is there some way for us to structure the code so that Pistons
can only be instantiated and used within the PetrolEngine
class? I.e. we get a compilation error if we try to use Piston
outside of PetrolEngine
?
Until tomorrow when I will reveal the answer.
Leave a Reply
Want to join the discussion?Feel free to contribute!