Opaque typer
Abstraksjoner uten kjørekostnad
Opaque typer er en gratis leksjon i Scala for backendutvikling og funksjonell programmering på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Scala for backendutvikling og funksjonell programmering, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Scala for backendutvikling og funksjonell programmering inneholder totalt 4 leksjoner.
Hva er opaque-typer?
Opaque-typer er en Scala 3-funksjon for å lage abstraksjoner uten kostnad. De gir en distinkt type ved kompilering, men kompileres til den underliggende typen uten innpakning ved runtime.
- Typesikkerheten til en wrapper-klasse.
- Ingen allokeringskostnad.
object Distances:
opaque type Meters = Double
object Main:
def main(args: Array[String]): Unit =
println("Opaque types compile to their underlying type")Deklarere en opaque-type
Deklarer en opaque-type inne i et objekt eller en klasse. Utenfor dette området behandles Meters og Double som forskjellige 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))Opaquenessens grense
Inne i området der den defineres, kan den opaque typen og den underliggende typen brukes om hverandre. Utenfor er bare den opaque typen synlig, så De kan ikke ved et uhell sende en rå Double der det kreves 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))Legge til extension-metoder
Gi opaque-typer funksjonalitet med extension-metoder definert i samme område. Kallere får praktiske operasjoner uten at den underliggende typen 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)Hindre sammenblandinger
Den store fordelen er at to opaque-typer over 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 grenser
De kan gi en opaque-type en øvre grense med <:. Dette eksponerer deler av det offentlige API-et, samtidig som den nøyaktige representasjonen holdes 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 konstruksjon med validering
Kombiner ugjennomsiktige typer med en validerende fabrikk for å sikre at verdiene alltid er gyldige. Konstruktøren forblir privat; bare den validerte fabrikken 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))Null kjøretidskostnad
I motsetning til en verdi- eller case class-innpakning oppretter en ugjennomsiktig type inget objekt under kjøring. En List av Meters er bokstavelig talt en liste med double-verdier i JVM-en, så det skjer 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)Ugjennomsiktig type kontra typealias
Et vanlig type X = Y-alias er transparent: X og Y kan brukes om hverandre overalt. En ugjennomsiktig type skjuler denne likheten utenfor virkeområdet sitt, og gir reell typesikkerhet.
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)Ugjennomsiktig type kontra case class-innpakning
En case class-innpakning som case class Meters(value: Double) gir også typesikkerhet, men oppretter et objekt. Ugjennomsiktige typer gir den samme sikkerheten med ytelsen til den underliggende typen.
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)Når bør De bruke ugjennomsiktige typer
Bruk ugjennomsiktige typer når De ønsker sterk domenetyping i ytelseskritiske kodebaner eller store samlinger.
- Skille mellom mengder (Meters kontra Seconds).
- Håndheve validerte invariansregler.
- Unngå allokeringskostnaden ved innpakninger.
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))Kort kontroll
Test forståelsen Deres av ugjennomsiktige typer.
Oppsummering
De har lært om ugjennomsiktige typer i Scala 3.
opaque type X = Yskjuler likheten utenfor virkeområdet sitt.- Tilby fabrikker og
extension-metoder som API. - Ulike ugjennomsiktige typer over samme basistype er inkompatible.
- Valgfrie øvre grenser med
<:eksponerer deler av API-et. - Null kjøretidskostnad, i motsetning til case class-innpakninger.
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 deg Scala med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 39
- Leksjoner
- 143
Ofte stilte spørsmål
Er leksjonen «Opaque typer» gratis?
Ja – hele teksten i «Opaque typer» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Scala for backendutvikling og funksjonell programmering-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Scala for backendutvikling og funksjonell programmering inneholder totalt 4 leksjoner.
Hva lærer jeg i «Opaque typer»?
Abstraksjoner uten kjørekostnad Du øver på Scala for backendutvikling og funksjonell programmering med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Scala for backendutvikling og funksjonell programmering?
Ingen tidligere erfaring er nødvendig. Scala for backendutvikling og funksjonell programmering på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Opaque typer»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Scala for backendutvikling og funksjonell programmering-leksjonen?
Ja. Alle Scala for backendutvikling og funksjonell programmering-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.