Constructeurs intelligents
Construction validée
Constructeurs intelligents est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Scala for Backend Engineering & Functional Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.
Construction validée
Un constructeur intelligent est une fabrique qui valide les entrées avant de produire une valeur. Il garantit que toute instance détenue respecte les invariants du type.
- Le constructeur brut est masqué.
- Seule la création validée est publique.
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))Constructeur privé
Déclarer le constructeur principal private empêche les appelants de contourner la validation. L’objet compagnon devient l’unique point d’entrée.
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))Renvoyer Option
Renvoyer Option indique que la construction peut échouer. L’appelant doit gérer None ; les données invalides ne circulent donc jamais silencieusement.
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))Renvoyer Either pour préciser l’erreur
Lorsque vous voulez expliquer pourquoi la validation a échoué, renvoyez Either[Error, T]. Left contient un message descriptif.
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))Constructeurs intelligents avec case class
Une case class avec un constructeur privé fonctionne également. Notez que son apply et son copy générés doivent aussi être contrôlés : définissez donc une fabrique personnalisée et gardez le constructeur privé.
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"))Enchaîner les valeurs validées
Comme les constructeurs intelligents renvoient Option ou Either, vous pouvez les composer avec des compréhensions for pour construire des objets validés plus complexes.
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"))Normaliser les entrées
Un constructeur intelligent peut également normaliser les données, par exemple en supprimant les espaces superflus ou en convertissant en minuscules, afin que toutes les instances partagent une forme canonique.
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 "))Les invariants sont conservés pour toujours
Une fois qu’une valeur a franchi le constructeur intelligent, son invariant est garanti pendant toute sa durée de vie. Le code en aval peut lui faire confiance sans effectuer une nouvelle vérification.
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)))Combiner avec des types opaques
Pour obtenir des valeurs validées sans coût supplémentaire, associez un constructeur intelligent à un type opaque. Aucun objet enveloppe n’est alloué, mais la validation contrôle toujours la construction.
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))Plusieurs règles de validation
Appliquez plusieurs vérifications successivement. La première règle qui échoue interrompt le traitement et renvoie une erreur claire.
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"))Quand utiliser les constructeurs intelligents
Utilisez-les dès qu’un type possède des invariants que la construction brute pourrait violer.
- Nombres bornés, chaînes non vides, identifiants au format correct.
- Renvoyez
Optionpour une simple réussite ou un simple échec, etEitherpour fournir les raisons. - Gardez le constructeur brut privé.
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))Vérification rapide
Vérifiez votre compréhension des constructeurs intelligents.
Récapitulatif
Vous avez appris les constructeurs intelligents.
- Validez les entrées dans une fabrique de l’objet compagnon.
- Rendez le constructeur brut privé.
- Renvoyez
OptionouEitherpour imposer la gestion des échecs. - Normalisez éventuellement les entrées dans une forme canonique.
- Les invariants sont alors conservés pendant toute la durée de vie de la valeur.
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))Questions Fréquemment Posées
La leçon « Constructeurs intelligents » est-elle gratuite ?
Oui — le texte complet de « Constructeurs intelligents » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Scala for Backend Engineering & Functional Programming, passe à CoddyKit PRO. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Constructeurs intelligents » ?
Construction validée Tu pratiques Scala for Backend Engineering & Functional Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Scala for Backend Engineering & Functional Programming ?
Aucune expérience préalable n'est requise. Scala for Backend Engineering & Functional Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Constructeurs intelligents » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Scala for Backend Engineering & Functional Programming ?
Oui. Chaque leçon Scala for Backend Engineering & Functional Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Modélisation avec les ADT
- Constructeurs intelligents
- Nouveaux types
- Composition des domaines