Opaque typer
Abstraktioner uden omkostninger
Opaque typer er en gratis Scala til backendudvikling og funktionel programmering-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Scala til backendudvikling og funktionel programmering, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Scala til backendudvikling og funktionel programmering-kurset indeholder 4 lektioner i alt.
Hvad er opaque-typer?
Opaque-typer er en funktion i Scala 3 til at oprette abstraktioner uden omkostninger. De giver en særskilt type ved kompilering, men kompileres til den underliggende type uden indpakning ved kørselstid.
- Typesikkerheden fra en wrapper-klasse.
- Ingen ekstra allokering.
object Distances:
opaque type Meters = Double
object Main:
def main(args: Array[String]): Unit =
println("Opaque types compile to their underlying type")Deklaration af en opaque-type
Deklarér en opaque-type i et objekt eller en klasse. Uden for dette scope behandles Meters og Double som forskellige typer.
object Distances:
opaque type Meters = Double
def meters(d: Double): Meters = d
def toDouble(m: Meters): Double = m
object Main:
def main(args: Array[String]): Unit =
val d = Distances.meters(5.0)
println(Distances.toDouble(d))Opaque-typens grænse
Inden for det scope, hvor typen defineres, kan den opaque type og dens underliggende type bruges om hinanden. Udenfor er kun den opaque type synlig, så du kan ikke ved et uheld sende en rå Double, hvor der kræves Meters.
object Distances:
opaque type Meters = Double
def apply(d: Double): Meters = d
def show(m: Meters): String = s"$m m"
object Main:
def main(args: Array[String]): Unit =
val m = Distances(10.0)
println(Distances.show(m))Tilføjelse af extension-metoder
Giv opaque-typer funktionalitet med extension-metoder, der defineres i samme scope. Kaldere får praktiske operationer uden at den underliggende type eksponeres.
object Distances:
opaque type Meters = Double
def apply(d: Double): Meters = d
extension (m: Meters)
def +(other: Meters): Meters = m + other
def value: Double = m
object Main:
def main(args: Array[String]): Unit =
val total = Distances(3.0) + Distances(4.0)
println(total.value)Forebyggelse af forvekslinger
Den store fordel er, at to opaque-typer over den samme underliggende type er inkompatible. Meters kan ikke forveksles med Kilometers, selv om begge er Doubles.
object Units:
opaque type Meters = Double
opaque type Kilometers = Double
def m(d: Double): Meters = d
def km(d: Double): Kilometers = d
def toMeters(k: Kilometers): Meters = k * 1000
object Main:
def main(args: Array[String]): Unit =
val far = Units.km(2.0)
println(Units.toMeters(far))Opaque-typer med grænser
Du kan give en opaque-type en øvre grænse med <:. Det eksponerer en del af den offentlige API, mens den præcise repræsentation forbliver skjult.
object Ids:
opaque type UserId <: Int = Int
def apply(i: Int): UserId = i
object Main:
def main(args: Array[String]): Unit =
val id = Ids(99)
println(id + 1)Smart konstruktion med validering
Kombinér opaque types med en validerende factory for at sikre, at værdier altid er gyldige. Konstruktøren forbliver privat; kun den validerede factory er offentlig.
object Ages:
opaque type Age = Int
def of(i: Int): Option[Age] =
if i >= 0 && i < 150 then Some(i) else None
extension (a: Age) def value: Int = a
object Main:
def main(args: Array[String]): Unit =
println(Ages.of(30).map(_.value))
println(Ages.of(-1))Ingen omkostning ved kørsel
I modsætning til en value class- eller case class-indpakning opretter en opaque type intet objekt ved kørsel. En List af Meters er bogstaveligt talt en liste af doubles på JVM'en, så der er ingen boxing.
object Temps:
opaque type Celsius = Double
def c(d: Double): Celsius = d
extension (t: Celsius) def value: Double = t
object Main:
def main(args: Array[String]): Unit =
val readings = List(Temps.c(20.0), Temps.c(21.5))
println(readings.map(_.value).sum)Opaque type kontra typealias
Et almindeligt type X = Y-alias er transparent: X og Y kan bruges fuldstændigt ombytteligt overalt. En opaque type skjuler denne lighed uden for sit scope og giver reel typesikkerhed.
object Demo:
type Name = String // transparent alias
opaque type Email = String // opaque
def email(s: String): Email = s
extension (e: Email) def raw: String = e
object Main:
def main(args: Array[String]): Unit =
val e = Demo.email("a@b.com")
println(e.raw)Opaque type kontra case class-indpakning
En case class-indpakning som case class Meters(value: Double) giver også typesikkerhed, men allokerer et objekt. Opaque types giver den samme sikkerhed med den rå types ydeevne.
object Money:
opaque type Cents = Long
def cents(n: Long): Cents = n
extension (c: Cents)
def +(o: Cents): Cents = c + o
def value: Long = c
object Main:
def main(args: Array[String]): Unit =
val total = Money.cents(150) + Money.cents(50)
println(total.value)Hvornår skal du bruge opaque types
Brug opaque types, når du ønsker stærk domænetypning i tidskritiske dele af programmet eller i store samlinger.
- Adskil størrelser som Meters og Seconds.
- Håndhæv validerede invariansregler.
- Undgå allokeringsomkostningen ved indpakninger.
object Geo:
opaque type Latitude = Double
def lat(d: Double): Option[Latitude] =
if d >= -90 && d <= 90 then Some(d) else None
extension (l: Latitude) def value: Double = l
object Main:
def main(args: Array[String]): Unit =
println(Geo.lat(41.0).map(_.value))Hurtigt tjek
Test din forståelse af opaque types.
Opsummering
Du har lært om Scala 3 opaque types.
opaque type X = Yskjuler ligheden uden for sit scope.- Stil factories og
extension-metoder til rådighed som API. - Forskellige opaque types baseret på den samme grundtype er inkompatible.
- Valgfrie øvre begrænsninger med
<:eksponerer en delmængde af API'et. - Ingen omkostning ved kørsel i modsætning til case class-indpakninger.
object Ids:
opaque type OrderId = String
def apply(s: String): OrderId = s
extension (o: OrderId) def raw: String = o
object Main:
def main(args: Array[String]): Unit =
val id = Ids("ORD-1")
println(id.raw)Lær Scala med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 39
- Lektioner
- 143
Ofte stillede spørgsmål
Er lektionen “Opaque typer” gratis?
Ja — hele teksten til “Opaque typer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Scala til backendudvikling og funktionel programmering-kurset, skal du opgradere til CoddyKit PRO. Scala til backendudvikling og funktionel programmering-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Opaque typer”?
Abstraktioner uden omkostninger Du øver dig i Scala til backendudvikling og funktionel programmering med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Scala til backendudvikling og funktionel programmering?
Der kræves ingen tidligere erfaring. Scala til backendudvikling og funktionel programmering på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Opaque typer”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Scala til backendudvikling og funktionel programmering-lektion?
Ja. Alle Scala til backendudvikling og funktionel programmering-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.