Guide
Generics and Interfaces
Interfaces with defaults, the built-in ones, generic Functions and types, constraints, and Where.
An Interface names Methods, Properties, and Operators a type promises, and can give Methods a
default. A generic Function or type takes type parameters, and constraints, which are
Interfaces, say what it can do with them. Each use of a generic is compiled for its types, so
generic code is as fast as code written for one type.
Interfaces
A Class implements an Interface by listing it and having its members. A value of the Interface’s type is an object of any Class that implements it.
Import std.core
Interface Damageable
Method Hurt(amount: Int)
ReadOnly Property Health: Int
Method Kill()
Hurt(Health)
End Method
End Interface
Class Crate Implements Damageable
Field hp: Int = 10
Method Hurt(amount: Int)
hp -= amount
End Method
Property Health: Int
Get => hp
End Property
End Class
Class Goblin Implements Damageable
Field hp: Int = 25
Method Hurt(amount: Int)
hp -= amount / 2
End Method
Property Health: Int
Get => hp
End Property
End Class
Local things: Damageable[] = [Crate(), Goblin()]
For t In things
t.Hurt(8)
Print(t.Health)
End For
things[1].Kill()
Print(things[1].Health)2 21 11
The built-in Interfaces
std.core’s Interfaces are what the language’s own operators and features go through:
| Interface | What it gives |
|---|---|
Equatable | == and != |
Comparable | <, >, <=, >=, and sorting |
Hashable | a Hash(), for Map keys and Set elements |
Printable | a ToString(), for strings and Print |
Numeric | +, -, *, /, Zero(), and One() |
Import std.core
Import std.collections
Struct Version Implements Comparable, Printable
Field major: Int
Field minor: Int
Operator ==(a: Version, b: Version): Bool => a.major == b.major && a.minor == b.minor
Operator <(a: Version, b: Version): Bool => a.major < b.major || (a.major == b.major && a.minor < b.minor)
Method ToString(): String => "{major}.{minor}"
End Struct
Local versions = [Version(1, 10), Version(0, 9), Version(1, 2)]
versions.Sort()
Print(versions)
Print(Version(1, 2) > Version(0, 9))[0.9, 1.2, 1.10] True
Generic Functions and types
Import std.core
Function Sum<T: Numeric>(values: T[]): T
Local total = T.Zero()
For v In values
total += v
End For
Return total
End Function
Class Stack<T>
Field items: T[] = []
Method Push(item: T)
items.Add(item)
End Method
Method Pop(): T?
If items.Count == 0 Then Return Null
Local top = items[items.Count - 1]
items.RemoveAt(items.Count - 1)
Return top
End Method
End Class
Print(Sum([1, 2, 3]), Sum([0.5, 0.25]))
Local undo = Stack<String>()
undo.Push("draw line")
undo.Push("fill")
Print(undo.Pop() ?? "", undo.Pop() ?? "", undo.Pop() ?? "nothing")6 0.75 fill draw line nothing
Type arguments are inferred from a call’s arguments where they can be, and written where they
can’t, as Stack<String>().
Where
A constraint goes inline, <T: Hashable>, when it’s one on one type parameter. More, or one
that relates two, go on Where lines; a Where on a Method makes it there only for the types
that meet it.
Import std.core
Class Bag<T>
Field items: T[] = []
Method Add(item: T)
items.Add(item)
End Method
Method Total(): T
Where T: Numeric
Local total = T.Zero()
For item In items
total += item
End For
Return total
End Method
End Class
Local coins = Bag<Int>()
coins.Add(5)
coins.Add(20)
Print(coins.Total())
Local names = Bag<String>()
names.Add("Ada")
Print(names.items)25 [Ada]
names.Total() wouldn’t compile, since a String isn’t Numeric.
Report an issue with this page or with FutureBlitz on GitHub.