Classes and traits

Classes support single inheritance with constructors and field defaults. Traits define shared behaviour across unrelated types. Both integrate with the type system.

Classes

The constructor method is named init. Instantiate with ClassName(args).

scratch.xs

Inheritance

Use class Dog : Animal to extend a class. Call super.init(...) to initialize parent fields. Methods can be overridden freely.

scratch.xs

Traits

Traits define a contract: a set of method signatures a type must implement. A type can implement multiple traits.

scratch.xs

Default methods

Traits can provide default implementations. Types only need to override them when they want different behaviour.

scratch.xs

Super traits and associated types

A trait can declare that implementing it also requires another trait. Traits can also declare associated type names.

trait Display {
  fn display(self) -> str
}

-- PrettyPrint requires Display to be implemented first
trait PrettyPrint: Display {
  fn pretty(self) -> str
}

-- associated type
trait Iterator {
  type Item
  fn next(self) -> Item
}

The semantic analyser enforces trait implementations: missing required methods, parameter count mismatches, and return type mismatches are all caught before execution.

When to use which

Use structs + traits when you have plain data that different parts of the codebase should process in different ways. The separation of data and behaviour keeps things composable.

Use classes when you need encapsulated mutable state, a natural inheritance hierarchy, or are modelling entities with identity (database rows, UI components, game objects).