LEVIATHAN v962456e · 962456eee1

leviathan-lang.com / docs / learn

Classes and objects

Members, constructors, labeled constructors, operators, and get/set properties.

A class is a set of members

Now the payoff of the "one rule." A class is a set of members, and a member is just a typed slot bound to a label. Some slots hold data; some hold something callable (a method). Constructors, operators, and properties are all members too: marked, not special-cased.

A class with constructors, a method, and operators

class Counter {
    public string label;
    public int value = 0;

    // A constructor is a member marked by 'new'. The name is only a label.
    new Counter(string startLabel) {
        label = startLabel;
    }
    // A second constructor, selected by its label rather than the class name.
    new WithValue(string startLabel, int start) {
        label = startLabel;
        value = start;
    }

    // A method. Arrow body: '=>' IS the return.
    string describe() => "${label} = ${value}";

    // An operator is a method whose name is a symbol.
    Counter (+)(int n) => Counter::WithValue(label, value + n);
    bool    (==)(int n) => value == n;     // (!=) derives automatically as !(==)
}

Constructing objects

Constructing takes no new at the call site. You name the type, or a labeled constructor:

Constructing and using a Counter

class Counter {
    public string label;
    public int value = 0;

    new Counter(string startLabel) {
        label = startLabel;
    }
    new WithValue(string startLabel, int start) {
        label = startLabel;
        value = start;
    }

    string describe() => "${label} = ${value}";

    Counter (+)(int n) => Counter::WithValue(label, value + n);
    bool    (==)(int n) => value == n;     // (!=) derives automatically as !(==)
}

Counter c = Counter("hits");            // -> label "hits", value 0
Counter d = Counter::WithValue("x", 3); // labeled constructor
Counter e = c + 5;                      // the (+) operator: value becomes 5
bool  hit = e == 5;                     // the (==) operator: true
console.writeln(c.describe());
console.writeln(d.describe());
console.writeln(hit);
console.writeln(e.describe());
console.writeln(e != 4);                // (!=) came for free
hits = 0
x = 3
true
hits = 5
true

Properties

Properties are typed views over a slot, declared with get and set. Objects are references (shared on assignment and passing); primitives and arrays are values.

A computed read/write property

class Thermostat {
    int celsius = 20;
    get fahrenheit() => celsius * 9 / 5 + 32;     // computed, read-only
    set fahrenheit(int f) celsius = (f - 32) * 5 / 9;
}

Thermostat t = Thermostat();
console.writeln(t.fahrenheit);
t.fahrenheit = 212;
console.writeln(t.celsius);
console.writeln(t.fahrenheit);
68
100
212

A field whose value is fixed once at construction is readonly; a compile-time constant field is const; a back-reference that shouldn't keep its target alive is weak. The reference entries on readonly fields, const, and weak fields have the details.

See also

  • readonly fields — Fix an instance field once, either in its initializer or in every constructor, and keep it read-only afterwards.
  • const declarations — Fix a local, field, global, parameter or loop binding after its initializer, with the exact rules for each kind of slot.
  • weak fields — Hold a non-owning reference to an object that reads as None once the object is gone.