Smarte konstruktører
Valideret konstruktion
Smarte konstruktører er en gratis Scala til backendudvikling og funktionel programmering-lektion på CoddyKit. Dette er lektion 2 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.
Valideret oprettelse
En smart konstruktør er en factory, der validerer input, før den producerer en værdi. Den garanterer, at enhver instans, du har, opfylder typens invariansregler.
- Den rå konstruktør er skjult.
- Kun valideret oprettelse er 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 konstruktør
Hvis du markerer den primære konstruktør med private, forhindrer du kaldere i at omgå valideringen. Companion-objektet bliver det eneste indgangspunkt.
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))Returnering af Option
Returnering af Option signalerer, at oprettelsen kan mislykkes. Kaldere skal håndtere None, så ugyldige data aldrig ubemærket føres videre.
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))Returnering af Either med fejloplysninger
Når du vil forklare, hvorfor valideringen mislykkedes, skal du returnere Either[Error, T]. Left indeholder en beskrivende meddelelse.
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))Smart-konstruktører med case class
En case class med en privat konstruktør fungerer stadig. Bemærk, at dens genererede apply og copy også skal styres, så definér en brugerdefineret factory, og hold konstruktøren 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"))Sammenkædning af validerede værdier
Fordi smart-konstruktører returnerer Option eller Either, kan du komponere dem med for-udtryk for at opbygge større validerede objekter.
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"))Normalisering af input
En smart-konstruktør kan også normalisere data, for eksempel ved at fjerne mellemrum eller konvertere til små bogstaver, så alle instanser har en kanonisk form.
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 "))Invariansregler gælder for altid
Når en værdi har bestået den smarte konstruktør, er dens invariansregel garanteret i hele dens levetid. Efterfølgende kode kan stole på værdien uden at kontrollere den 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)))Kombination med opaque types
Hvis du vil have validerede værdier uden omkostning ved kørsel, kan du kombinere en smart konstruktør med en opaque type. Der allokeres intet indpakningsobjekt, men valideringen styrer stadig oprettelsen.
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))Flere valideringsregler
Anvend flere kontroller i rækkefølge. Den første regel, der fejler, afbryder forløbet og returnerer en tydelig fejl.
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"))Hvornår skal du bruge smarte konstruktører
Brug dem, når en type har invariansregler, som en rå oprettelse kan overtræde.
- Tal inden for et bestemt interval, ikke-tomme strenge og formaterede id'er.
- Returnér
Optionved et simpelt ja/nej-resultat ogEither, når du vil angive årsagen. - Hold den rå konstruktør 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))Hurtigt tjek
Test din forståelse af smarte konstruktører.
Opsummering
Du har lært om smarte konstruktører.
- Validér input i en companion-factory.
- Gør den rå konstruktør privat.
- Returnér
OptionellerEitherfor at tvinge håndtering af fejl. - Normalisér om nødvendigt input til en kanonisk form.
- Derefter gælder invariansreglerne i hele værdiens levetid.
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 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 “Smarte konstruktører” gratis?
Ja — hele teksten til “Smarte konstruktører” 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 “Smarte konstruktører”?
Valideret konstruktion 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 2 af 4.
Hvor lang tid tager lektionen “Smarte konstruktører”?
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.
Alle lektioner i dette kursus
- Modellering med ADT'er
- Smarte konstruktører
- Newtypes
- Sammensætning af domæner