Котлин Вар и Вэл Проблема геттера и сеттера

Я новичок в языке программирования Kotlin. (Ява -> Котлин)

var x
    get()= 4; // Showing error Property must be initialized

val y
    get()= 4; // No error

Почему это происходит ?

Первый случай — это var, поэтому у него есть сеттер. Что вы ожидаете от сеттера в этом случае? Геттер всегда будет возвращать 4, но сеттер должен иметь возможность обновить какое-то значение. У вас есть реальный пример для этого?

Joffrey 27.11.2022 16:52

@ Джоффри, я думаю, что сеттер не указан.

Jithin Murali 27.11.2022 17:23

Вы не предоставили собственную реализацию установщика, но использование var заставляет Kotlin генерировать его по умолчанию. Пожалуйста, обратитесь к текущему ответу, в нем подробно объясняется, почему установщик по умолчанию делает этот код проблематичным. Однако мне было бы интересно узнать, действительно ли вы сталкивались с этой проблемой в реальной жизни.

Joffrey 27.11.2022 17:30
0
3
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

val y = 4 — это val, что означает, что он доступен только для чтения. Значение, которым вы его инициализируете, 4, хранится в резервном поле. Немного памяти, где хранится значение этой переменной.

var y = 4 — это var, что означает, что вы можете писать в него. Опять же, есть резервное поле, в котором хранится текущее значение — просто вы можете изменить его сейчас.


Вероятно, это все, к чему вы привыкли, но Kotlin также позволяет вам определять функции получения и установки, в зависимости от того, является ли это val (только геттер) или var. На самом деле геттеры и сеттеры по умолчанию уже существуют — они просто читают и записывают в резервное поле. Если вы не определяете свои собственные, он просто использует их.

val y get() = 4 — это val, что означает, что он доступен только для чтения. Поскольку вы добавили функцию получения, значение 4 на самом деле не сохраняется в резервном поле, поэтому Kotlin его не создает! Нечего инициализировать значением.

var y get() = 4 — это var, поэтому у вас есть возможность установить его. Вы не определили здесь функцию установки, поэтому она использует неявную функцию по умолчанию, которая записывает в резервное поле.

И вот в чем ваша проблема — Kotlin не создаст резервное поле, если оно ему не нужно:

// stores any value passed to the setter in the variable's backing field
var something
    get() = "hi"
    set(value) { field = value }

// does nothing with the setter value, no field is used anywhere, so it doesn't create one
var somethingElse
    get() = "hi"
    set(value) { }

(Это плохой пример, потому что обычно у вас не будет фиксированного значения с сеттером, потому что какой в ​​этом смысл? Но у вас может быть, скажем, пара геттер/сеттер, которая хранит и читает из карты или что-то еще, что не не требует резервного поля, так как оно получает и сохраняет данные в другом месте)


Итак, когда вы делаете var y get() = 4, вы эффективно делаете это:

var y
    get() = 4
    set(value) { field = value } // default setter

и это создает резервное поле через сеттер. И это поле должно иметь какое-то начальное значение! Kotlin не похож на Java таким образом, где вещи можно оставить неназначенными и по умолчанию использовать значение.

Итак, вам просто нужно присвоить значение:

var y = 1
    get() = 4

Теперь ваше вспомогательное поле имеет значение, так что компилятор доволен. На самом деле вы никогда не читали его, так что это бесполезно, и это хороший признак того, что вам вообще не нужен var!

Взгляните на документацию по свойствам , она объясняет все эти вещи (и некоторые другие вещи о видимости и т. д.), но, надеюсь, это имеет смысл, и вы понимаете, почему ваш пример на самом деле немного странный и чего-то, чего вы бы избегали.

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