Должен ли я использовать модификатор final при объявлении классов дел?
В соответствии с инструментом статического анализа scala-wartremover я должен ставить "final" перед каждым классом дел, который я создаю: в сообщении об ошибке говорится "классы дел должны быть окончательными".
По словам козла отпущения (еще один инструмент статического анализа для Scala), я не должен этого делать (сообщение об ошибке: "Избыточный конечный модификатор в классе дел")
Кто прав и почему?
1 ответ
Это не избыточно в том смысле, что его использование меняет вещи. Как и следовало ожидать, вы не можете расширить класс окончательного варианта, но вы можете расширить класс не конечного. Почему wartremover предполагает, что case-классы должны быть окончательными? Ну, потому что их расширение не очень хорошая идея. Учти это:
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
// ????
В самом деле? Bar(1,1)
равняется Bar(1,2)
? Это неожиданно Но подождите, это еще не все:
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) // ???
Копия Bar
имеет тип Foo
? Это может быть правильно?
Конечно, мы можем это исправить, переопределив .equals
(а также .hashCode
, а также .toString
, а также .unapply
, а также .copy
а также, возможно, .productIterator
, .productArity
, .productElement
и т.д.) метод на Bar
а также Baz
, Но "из коробки" любой класс, который расширяет класс case, будет сломан.
По этой причине вы больше не можете расширять класс case другим классом case, это было запрещено с тех пор, как мне кажется, scala 2.11. Расширение класса case не классом case все еще разрешено, но, по крайней мере, по мнению wartremover, это не очень хорошая идея.