The tour, 9 of 11
Interfaces and generics
Interfaces with default Methods, generic Functions and types, and constraints.
An Interface is what a type promises to have. A Class Implements it, and code that takes the
Interface takes an object of any of them. A Struct implements one too, for generic code, like a
<T: Shape>, though only Classes’ objects are the Interface’s values.
Import std.core
Interface Shape
Method Area(): Float
Method Describe(): String => "a shape of area {Area()}" // a default
End Interface
Class Circle Implements Shape
Field r: Float
New(r: Float)
Self.r = r
End New
Method Area(): Float => 3.14159 * r * r
End Class
Class Square Implements Shape
Field side: Float
New(side: Float)
Self.side = side
End New
Method Area(): Float => side * side
Method Describe(): String => "a square of side {side}"
End Class
Local shapes: Shape[] = [Circle(1), Square(2)]
For s In shapes
Print(s.Describe())
End Fora shape of area 3.14159 a square of side 2
Generics
A generic Function or type takes type parameters in angle brackets, and a constraint says what
they must implement. std.core’s built-in Interfaces, like Comparable, Equatable, Hashable,
Printable, and Numeric, are the usual ones.
Import std.core
Function Largest<T: Comparable>(items: T[]): T
Local best = items[0]
For item In items
If item > best Then best = item
End For
Return best
End Function
Class Box<T>
Field value: T
New(value: T)
Self.value = value
End New
Method Map<R>(f: Func(T): R): Box<R> => Box<R>(f(value))
End Class
Print(Largest([3, 9, 4]))
Print(Largest(["pear", "apple", "plum"]))
Local box = Box(21)
Print(box.Map(Function(x: Int) => x * 2).value)9 plum 42
The type arguments are worked out from the call when they can be, as Largest([3, 9, 4]) is a
Largest<Int>. Next: concurrency.
Report an issue with this page or with FutureBlitz on GitHub.