Smarta konstruktorer
Validerad konstruktion
Smarta konstruktorer är en gratis lektion i Scala för backendutveckling och funktionell programmering på CoddyKit. Detta är lektion 2 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.
Validerad konstruktion
En smart konstruktor är en fabrik som validerar indata innan den skapar ett värde. Den garanterar att varje instans Ni har uppfyller typens invariants.
- Den råa konstruktorn är dold.
- Endast validerad skapelse är offentlig.
class Age private (val value: Int)
object Age:
def of(v: Int): Option[Age] =
if v >= 0 then Some(new Age(v)) else None
object Main:
def main(args: Array[String]): Unit =
println(Age.of(30).map(_.value))Privat konstruktor
Genom att markera primärkonstruktorn som private hindrar Ni anropare från att kringgå valideringen. Kompanjonobjektet blir den enda ingångspunkten.
class Percentage private (val value: Int)
object Percentage:
def of(v: Int): Option[Percentage] =
if v >= 0 && v <= 100 then Some(new Percentage(v)) else None
object Main:
def main(args: Array[String]): Unit =
println(Percentage.of(50).map(_.value))
println(Percentage.of(150))Returnera Option
Att returnera Option signalerar att konstruktionen kan misslyckas. Anroparen måste hantera None, så ogiltiga data kan aldrig flöda vidare obemärkt.
class NonEmpty private (val value: String)
object NonEmpty:
def of(s: String): Option[NonEmpty] =
if s.nonEmpty then Some(new NonEmpty(s)) else None
object Main:
def main(args: Array[String]): Unit =
println(NonEmpty.of("").map(_.value))
println(NonEmpty.of("hi").map(_.value))Returnera Either för feldetaljer
När Ni vill förklara varför valideringen misslyckades returnerar Ni Either[Error, T]. Left innehåller ett beskrivande meddelande.
class Username private (val value: String)
object Username:
def of(s: String): Either[String, Username] =
if s.isEmpty then Left("empty")
else if s.length > 10 then Left("too long")
else Right(new Username(s))
object Main:
def main(args: Array[String]): Unit =
println(Username.of(""))
println(Username.of("ada").map(_.value))Smarta konstruktorer med case class
En case class med privat konstruktor fungerar fortfarande. Observera att dess genererade apply och copy också måste kontrolleras, så definiera en anpassad fabrik och behåll konstruktorn privat.
case class Email private (value: String)
object Email:
def of(s: String): Option[Email] =
if s.contains("@") then Some(Email(s)) else None
object Main:
def main(args: Array[String]): Unit =
println(Email.of("a@b.com"))
println(Email.of("bad"))Kedja validerade värden
Eftersom smarta konstruktorer returnerar Option eller Either kan Ni kombinera dem med for-uttryck för att bygga större validerade objekt.
case class Name private (value: String)
object Name:
def of(s: String): Option[Name] =
if s.nonEmpty then Some(Name(s)) else None
case class Person(name: Name, age: Int)
object Main:
def make(n: String): Option[Person] =
for nm <- Name.of(n) yield Person(nm, 20)
def main(args: Array[String]): Unit =
println(Main.make("Bob"))Normalisera indata
En smart konstruktor kan också normalisera data, till exempel genom att ta bort inledande och avslutande blanksteg eller konvertera till gemener, så att alla instanser har ett kanoniskt format.
case class Tag private (value: String)
object Tag:
def of(s: String): Option[Tag] =
val clean = s.trim.toLowerCase
if clean.nonEmpty then Some(Tag(clean)) else None
object Main:
def main(args: Array[String]): Unit =
println(Tag.of(" Scala "))Invariants gäller för alltid
När ett värde har godkänts av den smarta konstruktorn är dess invariant garanterad under hela dess livstid. Nedströms kod kan lita på värdet utan att kontrollera det igen.
case class PositiveInt private (value: Int)
object PositiveInt:
def of(n: Int): Option[PositiveInt] =
if n > 0 then Some(PositiveInt(n)) else None
object Main:
def doubleIt(p: PositiveInt): Int = p.value * 2 // always positive
def main(args: Array[String]): Unit =
PositiveInt.of(5).foreach(p => println(Main.doubleIt(p)))Kombinera med opaka typer
För validerade värden utan kostnad vid körning kan Ni kombinera en smart konstruktor med en opak typ. Inget wrapper-objekt allokeras, men valideringen styr fortfarande skapandet.
object Domain:
opaque type Score = Int
def of(n: Int): Option[Score] =
if n >= 0 && n <= 100 then Some(n) else None
extension (s: Score) def value: Int = s
object Main:
def main(args: Array[String]): Unit =
println(Domain.of(88).map(_.value))Flera valideringsregler
Tillämpa flera kontroller i följd. Den första regeln som misslyckas avbryter kedjan och returnerar ett tydligt fel.
object Password:
def of(s: String): Either[String, String] =
if s.length < 8 then Left("too short")
else if !s.exists(_.isDigit) then Left("need a digit")
else Right(s)
object Main:
def main(args: Array[String]): Unit =
println(Password.of("abc"))
println(Password.of("abcdef12"))När smarta konstruktorer bör användas
Använd dem när en typ har invariants som rå konstruktion kan bryta mot.
- Begränsade tal, icke-tomma strängar och formaterade id:n.
- Returnera
Optionför ett enkelt ja eller nej, ochEithernär Ni behöver ange orsaken. - Håll den råa konstruktorn privat.
case class Port private (value: Int)
object Port:
def of(n: Int): Option[Port] =
if n >= 1 && n <= 65535 then Some(Port(n)) else None
object Main:
def main(args: Array[String]): Unit =
println(Port.of(8080))
println(Port.of(70000))Snabbtest
Testa Er förståelse av smarta konstruktorer.
Sammanfattning
Ni har lärt Er om smarta konstruktorer.
- Validera indata i en fabrik i kompanjonobjektet.
- Gör den råa konstruktorn privat.
- Returnera
OptionellerEitherför att tvinga fram hantering av fel. - Normalisera vid behov indata till ett kanoniskt format.
- Invariants gäller därefter under hela värdets livstid.
case class Even private (value: Int)
object Even:
def of(n: Int): Option[Even] =
if n % 2 == 0 then Some(Even(n)) else None
object Main:
def main(args: Array[String]): Unit =
println(Even.of(4))
println(Even.of(5))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 ”Smarta konstruktorer” gratis?
Ja – hela texten till ”Smarta konstruktorer” 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 ”Smarta konstruktorer”?
Validerad konstruktion 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 2 av 4.
Hur lång tid tar lektionen ”Smarta konstruktorer”?
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
- Modellering med ADT:er
- Smarta konstruktorer
- Newtypes
- Att komponera domäner