Il existe deux types de modificateurs dans Scala: final
et sealed
Quelles sont les différences entre eux? Quand devriez-vous utiliser l'un sur l'autre?
Une classe final
ne peut pas être étendue, point.
Un trait sealed
ne peut être étendu que dans le même fichier source qu'il est déclaré. Ceci est utile pour créer des ADT (types de données algébriques). Un ADT est défini par la somme de ses types dérivés.
Par exemple.:
Option[A]
est défini par Some[A]
+ None
.List[A]
est défini par ::
+ Nil
.sealed trait Option[+A]
final case class Some[+A] extends Option[A]
object None extends Option[Nothing]
Car Option[A]
est scellé, il ne peut pas être étendu par d'autres développeurs - cela changerait son sens.
Some[A]
est définitif car il ne peut pas être prolongé, point final.
En prime, si un trait est scellé, le compilateur peut vous avertir si vos correspondances de motifs ne sont pas assez exhaustives car sait que Option
est limité à Some
et None
.
opt match {
case Some(a) => "hello"
}
Attention: la correspondance peut ne pas être exhaustive. Il échouerait sur l'entrée suivante:
None
sealed
classes (ou traits) peuvent toujours être héritées dans le même fichier source (où final
classes ne peuvent pas être héritées du tout).
Utilisez sealed
lorsque vous souhaitez restreindre le nombre de sous-classes d'une classe de base (voir "Type de données algébrique").
Comme l'un des avantages très pratiques d'une telle restriction, le compilateur peut maintenant vous avertir des correspondances de modèle non exaustives:
sealed trait Duo
case class One(i:Int) extends Duo
case class Two(i:Int, j:Int) extends Duo
def test(d:Duo) {
match {
case One(x) => println(x) // warning since you are not matching Two
}
}