Kotlin только для чтения свойство с и без getter

Эти эквиваленты?

  • val foo = someFooReturningFunction()

  • val foo get() = someFooReturningFunction()

Как я понял документацию, которую они были, но в моем собственном тестировании это не так.

С get () someFooReturningFunction() оценивается каждый раз при доступе к someFooReturningFunction() , без его оценки только один раз.

Они не эквивалентны. Пользовательский геттер действительно оценивается по каждому доступу к свойствам, аналогично нормальной функции, тогда как свойство val без пользовательских аксессуаров оценивается только один раз при инициализации (и фактически хранится в final поле на платформе JVM).

Вот как минимум несколько отличий:

  • Анализ потока управления и вывод nullability учитывают его, если свойство имеет пользовательский getter (или open и, следовательно, может быть переопределено с помощью пользовательского getter), потому что нет гарантии, что свойство возвращает одно и то же значение при последовательных вызовах:

     if (someObject.defaultGetterProperty != null) { someObject.defaultGetterProperty.let { println(it) } // OK } 

     if (someObject.propertyWithCustomGetter != null) { someObject.propertyWithCustomGetter { println(it) } // Error: cannot smart-cast } 
  • Когда свойство является private , если у него нет пользовательского getter, то получатель не генерируется вообще, и обратное поле обращается напрямую. Это, однако, деталь реализации, а не то, на что можно положиться.

Нет. В дополнение к причинам @ hotkey, вот простая демонстрация с использованием изменяемых свойств, показывающих, когда они определенно не эквивалентны. TLDR: если ваше свойство вычисляется с использованием свойства mutable, всегда используйте пользовательский getter над инициализатором.

 data class Calculation(val value1: Int, var value2: Int) { val sum: Int = value1 + value2 val sumWithGetter: Int get() = value1 + value2 } val calculation = Calculation(1, 2) println(calculation.sumWithGetter) // prints 3 println(calculation.sum) // prints 3 calculation.value2 = 0 println(calculation.sumWithGetter) // prints 1 (correct) println(calculation.sum) // prints 3!