Каждому языку необходимо определить, что является допустимым символом для идентификатора, а что нет. Частью рассмотрения будет простота разбора, часть должна состоять в том, чтобы избежать двусмысленности (другими словами, даже идеальный алгоритм синтаксического анализа не мог быть уверенным все время), часть будет предпочтительнее языкового дизайна (в случае с аналогией Java с C, C ++), а некоторые просто будут произвольными.
Точка в том, что это должно быть что-то, поэтому это то, что есть.
Я бы посчитал это особенностью, так как изменение val на var накладывает более слабые ограничения на использование и не может нарушить код суперкласса . Аналогичная ситуация может наблюдаться с модификаторами видимости:
trait A {
protected fun print() {
...
}
}
class AImpl: A {
public override fun print() {
...
}
}
В этом примере ограничения видимости также смягчаются подклассом, хотя некоторые люди рассматривают эту технику как антипаттерн.
Как защитить значения от изменения наследованием?
В kotlin вы можете явно определить, может ли какой-либо конкретный член класса быть переопределен подклассом с помощью модификатора open
. Однако в чертах все члены открыты по умолчанию. Решение состоит в том, чтобы заменить признак классом, чтобы вы могли контролировать наследование:
abstract class A {
fun print() {
...
}
val x : Int = 2;
}
class AImpl(x : Int) : A() {
override var x = x // compilation error
}