Union- en intersectietypen
Nieuwe typefuncties
Union- en intersectietypen is een gratis Scala voor backend-engineering en functioneel programmeren-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Scala voor backend-engineering en functioneel programmeren. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Scala voor backend-engineering en functioneel programmeren bevat in totaal 4 lessen.
Nieuwe typefuncties
Scala 3 voegt unietypen (A | B) en intersectietypen (A & B) toe aan het typesysteem. Hiermee kun je waarden nauwkeuriger beschrijven zonder overervingshiërarchieën.
object Main:
def main(args: Array[String]): Unit =
println("Union: A | B, Intersection: A & B")Basisprincipes van unietypen
Een unietype A | B stelt een waarde voor die een A of een B is. Het is een settheoretische OF over typen.
object Main:
def show(x: Int | String): String = x match
case i: Int => s"int $i"
case s: String => s"str $s"
def main(args: Array[String]): Unit =
println(show(42))
println(show("hi"))Unietypen hebben geen gemeenschappelijk supertype nodig
In tegenstelling tot Scala 2 Either vereisen unietypen geen wrapper. Je kunt twee willekeurige typen verenigen zonder dat ze dezelfde bovenliggende klasse hebben.
object Main:
def parse(input: Int | Boolean): String =
input match
case n: Int => s"number $n"
case b: Boolean => s"flag $b"
def main(args: Array[String]): Unit =
println(parse(7))
println(parse(true))Unietypen voor foutmodellering
Unietypen zijn handig voor lichtgewicht foutresultaten zonder een wrappertype. In combinatie met enums of singletons zijn ze duidelijk leesbaar.
case object NotFound
object Main:
def lookup(id: Int): String | NotFound.type =
if id == 1 then "Alice" else NotFound
def main(args: Array[String]): Unit =
println(lookup(1))
println(lookup(2))Basisprincipes van intersectietypen
Een intersectietype A & B stelt een waarde voor die zowel A als B is. Het is een settheoretische EN, die vaak wordt gebruikt om traits te combineren.
trait Named:
def name: String
trait Aged:
def age: Int
object Main:
def describe(p: Named & Aged): String =
s"${p.name} is ${p.age}"
def main(args: Array[String]): Unit =
val person = new Named with Aged:
def name = "Bob"
def age = 40
println(describe(person))Intersectie is commutatief
De volgorde is niet van belang voor intersectietypen: A & B is hetzelfde type als B & A. Dit verschilt van samengestelde typen in Scala 2, zoals A with B, waarbij de volgorde bij het oplossen van sommige leden wel van belang was.
trait Readable:
def read: String
trait Writable:
def write(s: String): Unit
object Main:
def use(r: Readable & Writable): Unit =
r.write("x")
println(r.read)
def main(args: Array[String]): Unit =
val rw = new Readable with Writable:
def read = "data"
def write(s: String) = println(s"wrote $s")
use(rw)Meerdere traits combineren
Je kunt meer dan twee typen kruisen. Het resultaat vereist alle vermelde mogelijkheden.
trait A: def a: Int
trait B: def b: Int
trait C: def c: Int
object Main:
def sum(x: A & B & C): Int = x.a + x.b + x.c
def main(args: Array[String]): Unit =
val v = new A with B with C:
def a = 1
def b = 2
def c = 3
println(sum(v))Typealiassen voor unietypen
Lange unietypen kun je een naam geven met een type-alias, zodat ondertekeningen leesbaar blijven.
type Json = Int | String | Boolean
object Main:
def render(j: Json): String = j match
case i: Int => i.toString
case s: String => s"\"$s\""
case b: Boolean => b.toString
def main(args: Array[String]): Unit =
println(render("hi"))
println(render(true))Volledig pattern matchen op unietypen
De compiler kent de leden van een unietype, zodat kan worden gecontroleerd of de afhandeling volledig is. Als je elk alternatief afhandelt, is de match totaal.
type Shape = "circle" | "square"
object Main:
def sides(s: Shape): Int = s match
case "circle" => 0
case "square" => 4
def main(args: Array[String]): Unit =
println(sides("square"))Verbreding van unietypen
Wanneer je een uniewaarde toewijst aan een variabele waarvan het type wordt afgeleid, behoudt Scala het unietype. Houd er rekening mee dat sommige bewerkingen het type verbreden naar de kleinste bovengrens. Gebruik daarom een typeannotatie als je het unietype wilt behouden.
object Main:
def pick(flag: Boolean): Int | String =
if flag then 1 else "one"
def main(args: Array[String]): Unit =
val x: Int | String = pick(false)
println(x)Wanneer gebruik je elk type
Kies het juiste hulpmiddel.
- Unie: een waarde is een van meerdere typen (OF).
- Intersectie: een waarde voldoet tegelijk aan meerdere traits (EN).
- Unies vermijden wrappertypen; intersecties vermijden diepe overerving.
trait Logger: def log(s: String): Unit
trait Clock: def now: Long
object Main:
def run(env: Logger & Clock): Unit =
env.log(s"time=${env.now}")
def main(args: Array[String]): Unit =
val env = new Logger with Clock:
def log(s: String) = println(s)
def now = 100L
run(env)Korte controle
Test je begrip van unie- en intersectietypen.
Samenvatting
Je hebt de unie- en intersectietypen van Scala 3 geleerd.
A | B: de waarde is A of B; een wrapper of gemeenschappelijke bovenliggende klasse is niet nodig.A & B: de waarde is zowel A als B; de volgorde is niet van belang.- Gebruik pattern matching om unies te verfijnen; combineer traits met intersecties.
- Gebruik
type-aliassen om lange unies een naam te geven.
object Main:
def length(x: String | List[Int]): Int = x match
case s: String => s.length
case l: List[Int] => l.length
def main(args: Array[String]): Unit =
println(length("hello"))
println(length(List(1, 2, 3)))Leer Scala met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 39
- Lessen
- 143
Veelgestelde vragen
Is de les “Union- en intersectietypen” gratis?
Ja — de volledige tekst van “Union- en intersectietypen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Scala voor backend-engineering en functioneel programmeren wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Scala voor backend-engineering en functioneel programmeren bevat in totaal 4 lessen.
Wat leer ik in “Union- en intersectietypen”?
Nieuwe typefuncties Je oefent met Scala voor backend-engineering en functioneel programmeren door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Scala voor backend-engineering en functioneel programmeren te beginnen?
Ervaring vooraf is niet nodig. Scala voor backend-engineering en functioneel programmeren op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Union- en intersectietypen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Scala voor backend-engineering en functioneel programmeren?
Ja. Elke les over Scala voor backend-engineering en functioneel programmeren bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Significante inspringing
- Enums in Scala 3
- Opaque types
- Union- en intersectietypen