Использование Scala частного окончательного модификатора?
Что я могу использовать модификатор private final
в Scala для?
Учитывая приведенный ниже код:
1| class A { def callFoo = foo; private final def foo = "bar of A" }
2| class B extends A { private final def foo = "bar of B"}
3| println((new A()).callFoo)
4| println((new B()).callFoo)
Линии 3 и 4 отпечатков:
1| bar of A
2| bar of A
Понятно, почему строка 2 не печатает bar of B
, потому что на самом деле существуют два определения foo
, а последнее в B не переопределяет первое в A. В противном случае Scala потребуется override
- вместо модификатора final
.
Итак, почему Scala не просто запрещает комбинацию модификаторов private final
?
Ответы
Ответ 1
Хорошо, это сложно. Ваш вопрос: "Так почему же Scala не просто запрещает комбинацию модификаторов private final?" основывается на предположении, что эта комбинация не используется.
Скажем, вы правы (и вы, за исключением крошечной детали, о которой будет сказано ниже). Я не компилятор, но с моей точки зрения "просто запретить", вероятно, не так просто (по крайней мере, в этом случае). И почему кто-то пытается это сделать? Каковы компромиссы? Только потому, что что-то не полезно, не обязательно означает, что он наносит какой-либо вред. Просто не используйте его...
Теперь вот крошечная деталь, которую вы, кажется, упустили. Модификатор private
является модификатором видимости, что означает, что class B
не знает о его существовании. Но модификаторы видимости Scala немного сложнее, чем Java. Предположим, что по какой-либо причине вам понадобится код, показанный в следующем фрагменте кода, компилятор не разрешит его.
package scope
class A {
def callFoo = foo;
private[scope] final def foo = "bar of A"
}
class B extends A {
private[scope] final def foo = "bar of B"
}
object Main extends App {
println((new A()).callFoo)
println((new B()).callFoo)
}
Это одна из ошибок, предоставляемых компилятором: "метод foo не может переопределить конечный элемент" .
Итак, вот и вы. Scala просто запрещает эту комбинацию;)
Ответ 2
Первоначально я думал, что это должно предотвратить переопределение частных методов во вложенных классах, но, по-видимому, не:
class A {
private final def foo = 0
class B extends A {
override def foo = 1
}
}
error: method foo overrides nothing
override def foo = 1
^
Возможно, это просто упростить рефакторинг? Итак, если у вас есть метод final
, попробуйте сделать его private
и найдите, что вам не нужно быть private
, в этом случае вы не потеряете final
ity?
Ответ 3
Обращаясь к более широкому вопросу,
Так почему же Scala не просто запрещает комбинацию модификаторов частный финал?
Это новое правило и, при этом, новое исключение. Это делает язык более сложным и совершенно не выигрывает. Зачем делать вещи более сложными без уважительной причины?
То, что делает Java, что Одерскому не нравится. Чтобы язык стал более сложным, должен быть некоторый выигрыш.