Your own types, 6 of 8
Interfaces
Say what a type can do with an Interface, implement it in several Classes, and use std.core's own.
What you’ll build
A notification system that can send a message by email, by text message, or to a log, and treats
each the same way. Then a Version type that sorts, through one of std.core’s Interfaces. An
Interface lists Methods a type must have, without saying how they work.
Declaring and implementing
An Interface lists Methods by their first lines alone. A Class that says Implements the
Interface must have each of them, with the same parameters and result, or it doesn’t compile.
Import std.core
Interface Notifier
Method Send(to: String, message: String)
End Interface
Class Email Implements Notifier
Method Send(to: String, message: String)
Print("email to {to}: {message}")
End Method
End Class
Class TextMessage Implements Notifier
Method Send(to: String, message: String)
Print("text to {to}: {message}")
End Method
End Class
Email().Send("ada", "Your order shipped.")
TextMessage().Send("ada", "Your order shipped.")email to ada: Your order shipped. text to ada: Your order shipped.
An Interface as a type
An Interface is a type too. A variable or array of it holds objects of any Class that implements
it, and a call through it runs the object’s own Method. Code written for Notifier works with
every kind of notifier, including ones written later.
Import std.core
Interface Notifier
Method Send(to: String, message: String)
End Interface
Class Email Implements Notifier
Method Send(to: String, message: String)
Print("email to {to}: {message}")
End Method
End Class
Class Log Implements Notifier
Field lines: Int
Method Send(to: String, message: String)
lines++
Print("log line {lines}: {to}: {message}")
End Method
End Class
Function Broadcast(notifiers: Notifier[], message: String)
For notifier In notifiers
notifier.Send("ops", message)
End For
End Function
Local log = Log()
Broadcast([Email(), log], "disk 90% full")
Broadcast([log], "backup done")email to ops: disk 90% full log line 1: ops: disk 90% full log line 2: ops: backup done
A Struct can implement an Interface too, for code that’s generic over types, but a value of an Interface type is always an object, never a Struct.
Default Methods
A Method in an Interface can have a body: a default, which every type that implements the
Interface gets unless it writes its own. Here every notifier can SendAll through its own Send.
Import std.core
Interface Notifier
Method Send(to: String, message: String)
Method SendAll(people: String[], message: String)
For person In people
Send(person, message)
End For
End Method
End Interface
Class TextMessage Implements Notifier
Method Send(to: String, message: String)
Print("text to {to}: {message}")
End Method
End Class
TextMessage().SendAll(["ada", "alan", "grace"], "The meeting moved to 3pm.")text to ada: The meeting moved to 3pm. text to alan: The meeting moved to 3pm. text to grace: The meeting moved to 3pm.
std.core’s Interfaces
The language works through Interfaces in std.core. A type that implements Printable, with a
ToString Method, can be printed. One that implements Comparable, with an Operator <, gets
>, <=, and >= from its defaults, and an array of it can Sort.
Import std.core
Import std.collections
Struct Version Implements Comparable, Printable
Field Major: Int
Field Minor: Int
Operator <(a: Version, b: Version): Bool
If a.Major != b.Major Then Return a.Major < b.Major
Return a.Minor < b.Minor
End Operator
Method ToString(): String => "{Major}.{Minor}"
End Struct
Local versions = [Version(1, 10), Version(1, 2), Version(0, 9)]
versions.Sort()
Print(versions)
Print(Version(1, 2) < Version(1, 10), Version(2, 0) >= Version(1, 9))[0.9, 1.2, 1.10] True True
Comparing Major, then Minor, as integers puts 1.2 before 1.10, which sorting their text
wouldn’t.
Operators on your own types covers Operator declarations.
What you learned
- An
Interfacelists Methods; a type thatImplementsit must have each one. - A value of an Interface type holds any implementing Class’s object, and calls run its Methods.
- A Method with a body in an Interface is a default, which types get unless they write their own.
Printablemakes a type printable, andComparablemakes it compare and sort.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.