Я новичок в языке программирования Kotlin. (Ява -> Котлин)
var x
get()= 4; // Showing error Property must be initialized
val y
get()= 4; // No error
Почему это происходит ?
@ Джоффри, я думаю, что сеттер не указан.
Вы не предоставили собственную реализацию установщика, но использование var
заставляет Kotlin генерировать его по умолчанию. Пожалуйста, обратитесь к текущему ответу, в нем подробно объясняется, почему установщик по умолчанию делает этот код проблематичным. Однако мне было бы интересно узнать, действительно ли вы сталкивались с этой проблемой в реальной жизни.
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
!
Взгляните на документацию по свойствам , она объясняет все эти вещи (и некоторые другие вещи о видимости и т. д.), но, надеюсь, это имеет смысл, и вы понимаете, почему ваш пример на самом деле немного странный и чего-то, чего вы бы избегали.
Первый случай — это
var
, поэтому у него есть сеттер. Что вы ожидаете от сеттера в этом случае? Геттер всегда будет возвращать 4, но сеттер должен иметь возможность обновить какое-то значение. У вас есть реальный пример для этого?