A trait names behavior that types can implement.
trait Summary {
fn summary(self): string
}Trait names use PascalCase; methods use snake_case.
Requirements
A method without a body is required.
trait Shape {
fn area(self): float
fn perimeter(self): float
}self denotes a receiver. mut self permits a method contract that updates
through the receiver.
Static requirements omit self.
trait Parse[T] {
fn parse(input: string): T
}Self
Self names the implementing type.
trait Merge {
fn merge(self, other: Self): Self
}This allows a requirement to relate inputs and outputs to the implementation target without introducing another type parameter.
Generics
Traits can declare type parameters.
trait Convert[T] {
fn convert(self): T
}A generic function can require a trait with concrete or parameterized arguments.
fn convert_all[A, B](values: []A): []B
where A: Convert[B] {
return values.map { value => value.convert() }
}Bounds
Use a where clause to state requirements on type parameters.
fn show[T](value: T): string
where T: Summary + Clone {
return value.summary()
}The checker makes only the bounded methods and operations available in the generic body. A later implementation cannot retroactively justify an unbounded call.
Supertraits
Place parent requirements after :.
trait Named: Summary {
fn name(self): string
}Implementing Named requires its Summary contract as well. Multiple
supertraits use +.
Supertrait cycles are rejected.
Defaults
A method body in a trait is a default implementation.
trait Named: Summary {
fn name(self): string
fn label(self): string {
return "${self.name()}: ${self.summary()}"
}
}An implementation inherits label unless it supplies an override. The
default body is still checked against the trait’s generic Self and bounds.
Associated types
An associated type lets an implementation choose a type tied to itself.
trait Source {
type Item
fn next(mut self): Option[Item]
}Implementations bind the associated type before methods using it are checked.
Associated types are useful when one implementation has one natural item type and making every call repeat that type parameter would be noisy.
Associated constants
Traits can declare associated constants and implementations can provide their values.
The declaration and binding forms are implemented, while the general application-facing lookup spelling is still being stabilized. Avoid exposing associated-constant access as a public dependency until its specification is final.
Sealing
@sealed restricts implementations to the trait’s declaring file.
@sealed
trait InternalNode {
fn lower(self): int
}Use sealing when exhaustive compiler knowledge or representation safety depends on controlling every implementation.
Opaque use
impl Trait accepts or returns a concrete value through a trait-only
interface.
fn area(shape: impl Shape): float {
return shape.area()
}This is statically dispatched. It is not a dynamically typed trait object.
Core traits
The prelude defines contracts including:
Equatable,Hashable, andComparable[T];DisplayandDebug;Numeric,Neg,Not, and bitwise operator traits;Default,Clone,From[T], andInto[T];Iterator[T]andIterable[T];Bytes,Buffer,Drop, andSelectable[T].
Their methods and laws are documented in Traits.
Dispatch
Trait dispatch is static. Generic calls are specialized for reachable concrete types, and the compiler records the implementation selected for each call.
Atoll currently has no dyn Trait spelling, runtime vtable contract, or
downcast operator. Use enums or anonymous unions when runtime alternatives
must remain explicit.