Version: v0.7.1 - Beta.  We welcome contributors & feedback.

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 fn drive {
        @.speed += @.engine.accelerate()
        print('Speed: ' ~ @.speed)
    }
}

// modules/Engine.tht
//----------------------------

class Engine {

    public fields {
        acceleration: 2,
    }

    public fn 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 moved away from inheritance because it quickly leads to rigid, hard to maintain, codebases.

Modern languages like Rust and Scala have shifted toward traits and object composition for code reuse among objects.

In an upcoming version, THT will support flexible Traits, similar to PHP's traits. In practice, traits behave like Multiple Inheritance in allowing you to combine code from multiple sources, but without many of the downsides.

Until then, composition is the way to go.