Что такое Котлин резервное поле для?
как разработчик Java, концепция резервного поля немного чужда мне. Дано:
class Sample {
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
}
что это резервное поле хорош? Kotlin docs сказал: классы в Котлине не могут иметь полей. Однако иногда необходимо иметь резервное поле при использовании пользовательских методов доступа. Зачем? В чем разница с использованием самого имени свойств внутри сеттера, например.
class Sample {
var counter = 0
set(value) {
if (value >= 0) this.counter = value // or just counter = value?
}
}
3 ответов:
, потому что, скажем, если у вас нет
fieldключевое слово, вы не сможете на самом деле установить/получить значениеget()илиset(value). Это позволяет получить доступ к полю резервного копирования в пользовательских методах доступа.это эквивалентный Java-код вашего образца:
class Sample { private int counter = 0; public void setCounter(int value) { if (value >= 0) setCounter(value); } public int getCounter() { return counter; } }по-видимому, это не хорошо, так как сеттер-Это просто бесконечная рекурсия в себя, никогда ничего не меняющая. Помните в Котлине, когда вы пишете
foo.bar = valueон будет переведен в сеттер звоните вместоPUTFIELD.
EDIT: Java имеет поля в то время как Котлин имеет свойства, что является довольно высоким уровнем концепции, чем поля.
есть два типа свойств: один с резервным полем, один без него.
свойство с резервным полем будет хранить значение в виде поля. Это поле позволяет хранить значение в памяти. Примером такого свойства является
firstиsecondсвойстваPair. Это свойство изменит представление в памятиPair.свойство без резервного поля должно будет хранить свое значение другими способами, чем непосредственно хранить его в памяти. Он должен быть вычислен из других свойств или самого объекта. Примером такого свойства является
indicesсвойство продленияList, который не поддерживается полем, но вычисленный результат на основеsizeсобственность. Так что это не изменит в памяти представлениеList(что он вообще не может сделать, потому что Java статически типизирован).
резервные поля хороши для запуска проверки или запуска событий при изменении состояния. Подумайте о том, сколько раз вы добавляли код в Java-сеттер / геттер. Резервное копирование полей было бы полезно в подобных сценариях. Вы будете использовать резервные поля, когда вам нужно контролировать или иметь видимость над сеттерами/геттерами.
при назначении поля с самим именем Поля вы фактически вызываете сеттер (т. е.
set(value)). В Примере у вас есть,this.counter = valueбудет рекурсировать в set(значение) пока мы не переполняем наш стек. Используяfieldобходит код сеттера (или геттера).
первоначально мне тоже было трудно понять эту концепцию. Поэтому позвольте мне объяснить вам это на примере.
рассмотрим этот класс Котлина
class DummyClass { var size = 0; var isEmpty get() = size == 0 set(value) { size = size * 2 } }теперь, когда мы смотрим на код, мы можем видеть, что он имеет 2 свойства т. е. -
size(С аксессорами по умолчанию) иisEmpty(с пользовательскими методами доступа). Но он имеет только 1 поле, т. е.size. Чтобы понять, что он имеет только 1 поле, давайте посмотрим Java-эквивалент этого класса.перейти к Инструменты - > Kotlin - > показать байт-код Kotlin в Android Studio. Нажмите на кнопку декомпилировать.
public final class DummyClass { private int size; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.size == 0; } public final void setEmpty(boolean value) { this.size *= 2; } }ясно, что класс java имеет только функции getter и setter для
isEmpty, и для него нет объявленного поля. Точно так же в Котлине нет резервного поля для свойстваisEmpty, так как свойство не зависит от этого поля вообще. Таким образом, нет резервного поля.
теперь давайте удалим пользовательский геттер и сеттер
isEmptyсвойство.class DummyClass { var size = 0; var isEmpty = false }и эквивалент Java вышеуказанного класса
public final class DummyClass { private int size; private boolean isEmpty; public final int getSize() { return this.size; } public final void setSize(int var1) { this.size = var1; } public final boolean isEmpty() { return this.isEmpty; } public final void setEmpty(boolean var1) { this.isEmpty = var1; } }здесь мы видим, как поля
sizeиisEmpty.isEmpty- это резервное поле, потому что геттер и сеттер дляisEmptyсвойство зависит от него.
Comments