web-dev-qa-db-fra.com

Dois-je utiliser le dernier modificateur lors de la déclaration des classes de cas?

Selon scala-wartremover outil d'analyse statique, je dois mettre "final" devant chaque classe de cas que je crée: le message d'erreur dit "les classes de cas doivent être finales".

Selon bouc émissaire (un autre outil d'analyse statique pour Scala), je ne devrais pas (message d'erreur: "Modificateur final redondant sur la classe de cas")

Qui a raison et pourquoi?

50
sscarduzio

Ce n'est pas redondant dans le sens où son utilisation change les choses. Comme on peut s'y attendre, vous ne pouvez pas étendre une classe de cas finale, mais vous pouvez étendre une classe non finale. Pourquoi wartremover suggère-t-il que les classes de cas soient finales? Eh bien, parce que les étendre n'est pas vraiment une très bonne idée. Considère ceci:

scala> case class Foo(v:Int)
defined class Foo

scala> class Bar(v: Int, val x: Int) extends Foo(v)
defined class Bar

scala> new Bar(1, 1) == new Bar(1, 1)
res25: Boolean = true

scala> new Bar(1, 1) == new Bar(1, 2)
res26: Boolean = true
// ????

Vraiment? Bar(1,1) est égal à Bar(1,2)? C'est inattendu. Mais attendez, il y a plus:

scala> new Bar(1,1) == Foo(1)
res27: Boolean = true

scala> class Baz(v: Int) extends Foo(v)
defined class Baz

scala> new Baz(1) == new Bar(1,1)
res29: Boolean = true //???

scala> println (new Bar(1,1))
Foo(1) // ???

scala> new Bar(1,2).copy()
res49: Foo = Foo(1) // ???

Une copie de Bar a le type Foo? Cela peut-il être vrai?

Certes, nous pouvons résoudre ce problème en remplaçant le .equals (Et .hashCode, Et .toString, Et .unapply, Et .copy, Et aussi , éventuellement, .productIterator, .productArity, .productElement etc.) méthode sur Bar et Baz. Mais "prêt à l'emploi", toute classe qui étend une classe case serait rompue.

C'est la raison pour laquelle vous ne pouvez plus étendre une classe de cas par une autre classe de cas, cela a été interdit depuis, je pense scala 2.11. L'extension d'une classe de cas par une classe non-cas est toujours autorisé, mais, au moins, de l'avis de wartremover n'est pas vraiment une bonne idée.

86
Dima