Как компилятор kotlin знает, должен ли val быть свойством или функцией

Следующий код котлинаval nameHash get() = name.hashCode()может быть скомпилирован в java следующим образом

      public final int getNameHash() {
    return name.hashCode();
}

и свойство nameHash исчезает. Однако, когда val изменяется на var, компилятор говорит: «Свойство должно быть инициализировано». В чем более глубокая разница между var и val?

2 ответа

Как компилятор kotlin знает, должен ли val быть свойством или функцией

Что касается языка Kotlin , то обозначает свойства, а не функции. Однако между этими двумя объявлениями свойств есть разница:

      val nameHash get() = name.hashCode()
var nameHash get() = name.hashCode()

И это то, что первое свойство не имеет резервного поля . Свойства с резервными полями должны быть так или иначе инициализированы, например:

      var nameHash = 0 // for example
    get() = name.hashCode()

И именно поэтому ваш код сvarне скомпилировал.

Если вы спрашиваете о ситуациях, когда резервное поле создается для свойства Kotlin, они перечислены в спецификации:

Однако резервное поле создается для свойства только в следующих случаях.

  • У свойства нет пользовательских методов доступа;
  • У свойства есть метод доступа по умолчанию;
  • Свойство имеет настраиваемый метод доступа и используетfieldсвойство;
  • Изменяемое свойство имеет настраиваемый геттер или сеттер, но не оба.

Это те случаи, когда вашему объекту требуется резервное поле. Твойvar nameHashудовлетворяет этому последнему случаю, потому что это «изменяемое свойство». Если вы используетеvalвместо этого оно больше не является изменяемым свойством и не удовлетворяет ни одному из этих случаев.

Интуитивно понятно, что изменяемое свойство без установщика нуждается в резервном поле, потому что нужно иметь возможность устанавливать свойство. Как вы можете установить его, если у него нет сеттера? Что ж, компилятор Kotlin решает проблему, генерируя резервное поле и вместо этого просто устанавливая резервное поле.

Свойство представляет собой функции & . Свойства только для чтения реализуют только функцию, но, тем не менее, это функция, поэтому все, что написано в свойстве, будет выполняться каждый раз при его вызове.

В Котлине ключевые слова:valсовпадает со свойством только для чтения, то есть требуется только для реализации функции. Когда вы положилиvarключевое слово, компилятор ожидает, что вы реализуете обаget()& функции.

Итак, ошибка компиляции, потому что ваше свойство отсутствуетset()функция, которая обычно нужна для хранения значения (или, как говорит компилятор: должна быть инициализирована).

Другие вопросы по тегам