Design note: why EK9 favours composition over inheritance

This note goes with Composition in EK9, which asks why EK9 labours traits and composition so much. These are opinions, and you may think them incorrect, opinionated or extreme. EK9 has been driven partly by experience: of 'C' and structs, and of the joy and pain of object-oriented programming.

From structs to class hierarchies

When object-oriented programming started to gain ground, defining data structures ('structs' in C) and manipulating them with functions fell out of use. Object-oriented developers considered that a good thing, and classes and class hierarchies became the main driving force. The first classes were relatively simple to understand. Before long, very large and deep hierarchies were common, in many cases with multiple inheritance adding to the complexity.

The main reason the 'new OOP' approach was a good thing is that it hid data and limited access to state, specifically its mutation. EK9 gets that protection another way, with pure, and so can use records and functions again without the 'getters' that spread through OOP code bases.

How the rot set in

Why composition was not used more

It was not made easy enough. Imagine a trait/interface with 20 methods, and a class that implements all 20. To compose that class with another that implements the same trait/interface, you write 20 methods that only call delegate.{methodName}.

EK9's by does that for you. A class can have several traits, and each trait, with all its methods, can be delegated to a concrete class that already exists. Override a few of those methods and EK9 does not delegate them. Delegation becomes as easy as inheritance, so you can choose it on its merits.

The composition example shows the result on a design that would otherwise need a class hierarchy with multiple inheritance.