Scala för backendutveckling och funktionell programmering · Lektion

Unionstyper och snittstyper

Nya typfunktioner

Lektion 4 av 413 steg

Unionstyper och snittstyper är en gratis lektion i Scala för backendutveckling och funktionell programmering på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Scala för backendutveckling och funktionell programmering, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 4 lektioner.

Nya typfunktioner

Scala 3 lägger till uniontyper (A | B) och snitttyper (A & B) i typsystemet. De låter Er beskriva värden mer precist utan arvshierarkier.

object Main:
  def main(args: Array[String]): Unit =
    println("Union: A | B, Intersection: A & B")

Grunderna i uniontyper

En uniontyp A | B representerar ett värde som antingen är en A eller en B. Den motsvarar ett mängdteoretiskt ELLER över typer.

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"))

Unioner kräver ingen gemensam supertyp

Till skillnad från Scala 2:s Either kräver uniontyper ingen inpackning. Vilka två typer som helst kan förenas utan att ha en gemensam föräldraklass.

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))

Unioner för felmodellering

Uniontyper är praktiska för enkla felresultat utan en wrapper-typ. Tillsammans med enumtyper eller singletoner blir de lättlästa.

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))

Grunderna i snitttyper

En snittyp A & B representerar ett värde som är både A och B. Den motsvarar ett mängdteoretiskt OCH och används ofta för att kombinera traits.

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))

Snitt är kommutativa

Ordningen spelar ingen roll för snitttyper: A & B är samma typ som B & A. Detta skiljer sig från Scala 2:s sammansatta typer A with B, där ordningen påverkade vissa medlemsupplösningar.

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)

Kombinera flera traits

Ni kan ta snittet av fler än två typer. Resultatet kräver alla angivna egenskaper.

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))

Typalias för unioner

Långa uniontyper kan namnges med ett type-alias för att hålla signaturerna lättlästa.

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))

Fullständig mönstermatchning på unioner

Kompilatorn känner till medlemmarna i en union, så den kan kontrollera att matchningen är fullständig. När varje alternativ hanteras blir matchningen total.

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"))

Breddning av unioner

När Ni tilldelar ett unionsvärde till en variabel vars typ härleds behåller Scala uniontypen. Var medveten om att vissa operationer breddar typen till den minsta övre begränsningen, så ange typen uttryckligen när Ni vill bevara unionen.

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)

När de olika typerna bör användas

Välj rätt verktyg.

  • Union: ett värde är en av flera typer (ELLER).
  • Snitt: ett värde uppfyller flera traits samtidigt (OCH).
  • Unioner undviker wrapper-typer; snitt undviker djupa arvshierarkier.
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)

Snabbtest

Testa Er förståelse av uniontyper och snitttyper.

Sammanfattning

Ni har lärt Er om uniontyper och snitttyper i Scala 3.

  • A | B: värdet är A eller B; ingen wrapper eller gemensam förälder behövs.
  • A & B: värdet är både A och B; kommutativt.
  • Använd mönstermatchning för att begränsa unioner; kombinera traits med snitt.
  • Använd type-alias för att namnge långa unioner.
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)))
Gratis att börja

Lär dig Scala med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
39
Lektioner
143

Vanliga frågor

Är lektionen ”Unionstyper och snittstyper” gratis?

Ja – hela texten till ”Unionstyper och snittstyper” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Scala för backendutveckling och funktionell programmering, kan Ni uppgradera till CoddyKit PRO. Kursen i Scala för backendutveckling och funktionell programmering innehåller totalt 4 lektioner.

Vad lär jag mig i ”Unionstyper och snittstyper”?

Nya typfunktioner Ni övar på Scala för backendutveckling och funktionell programmering med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Scala för backendutveckling och funktionell programmering?

Du behöver inga förkunskaper. Utbildningen i Scala för backendutveckling och funktionell programmering på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Unionstyper och snittstyper”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Scala för backendutveckling och funktionell programmering-lektionen?

Ja. Varje Scala för backendutveckling och funktionell programmering-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Signifikant indentering
  2. Enumtyper i Scala 3
  3. Opaque Types
  4. Unionstyper och snittstyper
← Tillbaka till Scala för backendutveckling och funktionell programmering