Combining Objects
Favor object composition over class inheritance.
— The “Gang of Four”, Design Patterns
Object Composition
THT supports a style of object-oriented programming that relies on object composition — the technique of combining smaller objects to create bigger, more complex objects.
You can combine objects in any way — even at run-time — while maintaining a clean separation between the individual objects (i.e. encapsulation).
Example
For example, a Car
object might contain an Engine
object.
In turn, the Engine
might be made up of sub-objects for FuelIntake
, Ignition
, SpinnyThing
etc.
(I clearly don’t know car stuff.)
All of the sub-objects work together as one system, but each part is self-contained.
+------------------------+ | Car | | | | +------------------+ | | | Engine | | | | | | | | [] FuelIntake | | | | [] Ignition | | | | [] SpinnyThing | | | | | | | +------------------+ | +------------------------+
How It Works
To compose objects, simply assign a sub-object to a field.
In the car example, we will assign an Engine object to the Car object.
// modules/Car.tht //---------------------------- class Car { public fields { engine: Engine({ acceleration: 5 }) speed: 0 } public fun drive { @.speed += @.engine.accelerate() print('Speed: ' ~ @.speed) } } // modules/Engine.tht //---------------------------- class Engine { public fields { acceleration: 2 } public fun accelerate { print('Vroooom!') return @.acceleration } }
And then to use them:
$car = Car() $car.drive() //= 'Vroooom!' //= Speed: 5
Because Engine is a public field, you could pass a new one in to initializer.
$fastCar = Car({ engine: Engine({ acceleration: 20 }) }) $fastCar.drive() //= 'Vroooom!' //= Speed: 20 $fastCar.drive() //= 'Vroooom!' //= Speed: 40
What About Inheritance?
Over the past decade or so, the software industry has gradually tried to shift away from overuse of inheritance because it can quickly lead to rigid, hard-to-maintain, codebases.
For example, modern languages like Rust and Scala instead use traits and object composition for code reuse among objects.
In an upcoming version, THT will probably support Mixins, similar to PHP's Traits but with more cleaner separation of concerns. This will allow you to reuse code from multiple sources, but without many of the downsides of inheritance.
Until then, composition is the way to go.