Vivere
Vivere

Reputation: 2280

What does composition mean in the composition vs inheritance debate?

I was learning about the Bridge Design pattern. To quote:

The Bridge pattern attempts to solve this problem by switching from inheritance to the object composition. …

And then, the following image is shown:

Bridge Pattern

When people are talking about composition as an alternative for inheritance, do they refer to both aggregation and composition relationships? If not, what do they mean exactly?

I wonder this because the picture has an aggregation relationship between Color and Shape, not a composition one.

Upvotes: 4

Views: 826

Answers (3)

Christophe
Christophe

Reputation: 73406

In short

This is a terminological ambiguity. Almost all articles on the bridge pattern are directly inspired from the Gang of Four (GoF) who first defined this design pattern. And this is the cause of the ambiguity:

  • They used the term composition to mean object composition and not UML composition.

  • At the time they wrote their book, UML was not yet defined. Their graphical notation uses the hollow diamond with a different meaning than UML.

  • They were first to mention composition over inheritance, with the meaning of object composition as opposed to class inheritance.

More details

GoF's object composition is not UML composition

Object composition is the OOP technique that aims at making more complex objects by assembling simpler objects. It's defined on page 19 of the book:

Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of the objects are visible.

In UML this technique corresponds to the implementation of an association, a shared aggregation or an UML composition. But unlike UML composition, it does not imply exclusive ownership nor lifecycle management.

GoF graphical notation is not UML

The graphical notation of class diagram used in the book looks very much like UML. This is because it is based on OMT, a predecessor of UML. But there are slight differences in the use of symbols, as you can read on page 364 of GoF:

An object reference representing a part-of or aggregation relationship is indicated by an arrowheadded line with a diamond at its base.

In UML, a composition (black diamond) would match this definition. But UML-composition adds more requirement, such as an exclusive ownership and responsibility for the component's lifecycle. This is more restrictive than object composition and reference-based aggragation.

In UML a shared aggregation (hollow diamond) or even a simple association (no diamond) would also perfectly match this definition, keeping in mind that UML does not define the semantics of shared aggregation.

Composition over inheritance

GoF are as far as I know, the first who recommended composition over inheritance. Page 20 of their pioneering work they made the following very precise statement (highlighting by me):

Favor object composition over class inheritance

We all like short mantras. Hence, this was quickly taken over without "object" and "class".

Conclusion

Whenever people speak about GoF patterns, you'll face the risk that aggregation or composition symbols might not be accurate, and that composition could have several meanings. So, you need to read it with critical thinking and an open mind. As patterns are not magical recipes, and may anyway need to be adapted to your own constraints, this state of mind can only be of advantage for you ;-)

Upvotes: 5

www.admiraalit.nl
www.admiraalit.nl

Reputation: 6089

I can't say what "people" refer to when they talk about composition as an alternative for inheritance, so I will speak for myself.

I think both composition (filled diamond) and shared aggregation (open diamond) are valid, but composition is preferred in most cases.

Shared aggregation implies that it is allowed to have one Color instance aggregated by multiple Shape instances. This is valid, since there may be multiple red shapes, for instance, and there is no reason for these shapes to have their own copy of Red.

However, in practice, the components will have attributes of their own. For example, class Color might have attribute 'brightness'. Now, if an instance of Red is shared by multiple Shapes and one of these Shapes changes its brightness, then all other red shapes have their brightness changed as well. This is usually not desirable. In such a case, composition is preferred.

Upvotes: 1

Matt Timmermans
Matt Timmermans

Reputation: 59184

Normally, when people talk about using composition vs. inheritance, they are talking about alternative ways of solving the same problem. In both cases, a "base class" provides an implementation of an interface that you want to reuse in your "derived class"

When you implement this with inheritance, there is an undesirable is-a relationship between the derived class and the base class, with the effect that implementation details of the base class, which should be hidden, can become changes in the derived class class.

When you implement this with composition -- a real composition relationship -- the "derived" only has an is-a relationship with the interface that it wants to implement, and the cost of this is that it must delegate calls to the "base" class.

In the Bridge pattern, which you reference, the goal is a little different. You do want to isolate the containing class from change to the connected implementation, but there is no is-a relationship between the containing class and an interface of the contained class.

The relationship between them may be one of composition, or may be simple aggregation -- that is an implementation detail. Often, the concrete implementation of the contained class will be injected as an interface into the containing class constructor, and in that case the relationship is just aggregation.

Upvotes: 1

Related Questions