Opaque Types
An opaque type is a type alias whose real type is hidden outside its defining object. It keeps the underlying type private while the program still works with values of the new type.
An opaque type hides its underlying type
The object defines Meter from Double. The program builds one Meter and reads its value through an operation.
object Meters:
opaque type Meter = Double
def from(d: Double): Meter = d
extension (m: Meter)
def value: Double = m
def plus(other: Meter): Meter = m + other
def doubled: Meter = m + m
@main def main(): Unit =
import Meters.*
val m = Meters.from(3.5)
println(m.value)An extension method adds a plus operation
The plus operation joins two Meters. The program prints the value of the joined Meter.
object Meters:
opaque type Meter = Double
def from(d: Double): Meter = d
extension (m: Meter)
def value: Double = m
def plus(other: Meter): Meter = m + other
def doubled: Meter = m + m
@main def main(): Unit =
import Meters.*
val a = Meters.from(3.5)
val b = Meters.from(2.5)
println(a.plus(b).value)An extension method can double a Meter
The doubled operation adds a Meter to itself. The program prints the doubled value.
object Meters:
opaque type Meter = Double
def from(d: Double): Meter = d
extension (m: Meter)
def value: Double = m
def plus(other: Meter): Meter = m + other
def doubled: Meter = m + m
@main def main(): Unit =
import Meters.*
val m = Meters.from(3.5)
println(m.doubled.value)Example
object Meters:
opaque type Meter = Double
def from(d: Double): Meter = d
extension (m: Meter)
def value: Double = m
def plus(other: Meter): Meter = m + other
def doubled: Meter = m + m
@main def main(): Unit =
import Meters.*
val a = Meters.from(2.0)
val b = Meters.from(3.0)
val total = a.plus(b)
println(total.value)
println(total.doubled.value)Key points
- Defining object: An opaque type is declared inside an object with the word opaque.
- Hidden outside: Outside the object, the new name is not treated as the underlying type.
- Extension method: An extension method adds an operation to values of the new type.
- Builder: A method inside the object builds a value of the opaque type from an ordinary value.
- Access: Outside code reads the hidden value only through operations the object provides.
In this example, the program builds two Meters from 2.0 and 3.0. It joins them into a total of 5.0. It doubles the total to get 10.0.
Note
A plain alias never hides its underlying type, but an opaque type does.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
How does outside code read the value inside an opaque type?