Classes & types
Langoost supports objects, named types, and classes with single inheritance.
Objects
The simplest structured value is an object literal — keys mapped to values, accessed with dot or bracket notation:
let point = {x: 3, y: 4}
println(point.x) // 3
point["y"] = 5 // update, or add a new key
Keys may also be written as string literals, which is handy for keys that aren’t identifiers (e.g. building queries):
let update = {"$set": {status: "active"}}
Objects are also Langoost’s map type. See types & values.
Type declarations
Give an object shape a name with type. This documents the structure and lets
you construct values with Name{...}:
type User = {
id: int,
name: string,
email: string,
}
let u = User{id: 1, name: "alice", email: "alice@example.com"}
println(u.name) // "alice"
Types describe structure; fields are not enforced at runtime (duck typing).
Classes
A class groups methods. Construct an instance with ClassName{...} (setting
any fields), then call its methods with dot syntax:
class Counter {
fn increment() {
self.count += 1
return self.count
}
fn value() {
return self.count
}
}
let c = Counter{count: 0}
c.increment()
c.increment()
println(c.value()) // 2
Inside a method, self refers to the instance.
Inheritance
A class can extend one parent and call the parent’s implementation with
super:
class Animal {
fn speak() {
return "..."
}
fn describe() {
return "I say " + self.speak()
}
}
class Dog extends Animal {
fn speak() {
return "woof"
}
}
let d = Dog{}
println(d.describe()) // "I say woof"
Interfaces
An interface names a set of methods a value must provide. Interfaces are
checked at runtime with the is and as operators:
interface Reader {
fn read()
fn close()
}
fn consume(x) {
if x is Reader { // → bool
let r = x as Reader // → x, or throws if it doesn't satisfy Reader
process(r.read())
r.close()
}
}
x is Reader returns a bool; x as Reader returns the value if it satisfies
the interface, or throws {kind: "InterfaceMismatch", message, want, got}
otherwise. The check walks a class’s parent chain. (Generics are deferred —
without static type checking they would be cosmetic.)
Notes
Langoost classes are intentionally small. There are no constructors
(initialize fields in the Name{...} literal), and no static members or
visibility modifiers. For error types and recoverable failures, see
error handling.