val y = 4 is a val, which means it's read-only. The value you're initialising it with, 4, is stored in a backing field. A bit of memory where the value of that variable is stored.
var y = 4 is a var, which means you can write to it. Again, there's a backing field storing the current value - it's just that you can change it now.
This is probably all stuff you're used to - but Kotlin also allows you to define getter and setter functions, depending on whether it's a val (getter only) or var. In reality, default getters and setters already exist - they just read from and write to the backing field. If you don't define your own, it just uses those.
val y get() = 4 is a val, which means it's read-only. Because you've added a getter function, the 4 value isn't actually stored in a backing field - so Kotlin doesn't create one! There's nothing to initialise with a value.
var y get() = 4 is a var, so you have the ability to set it. You haven't defined a setter function here, so it's using the implicit default one, which writes to the backing field.
And that's where your problem is - Kotlin won't create a backing field if it doesn't need one:
// 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) { }
(It's not a good example because generally you wouldn't have a fixed value with a setter, because what's the point? But you could have, say, a getter/setter pair that stores and reads from a map or something, which doesn't require a backing field since it's getting and storing the data elsewhere)
So when you do var y get() = 4 you're effectively doing this:
var y
get() = 4
set(value) { field = value } // default setter
and that's creating a backing field through the setter. And that field needs to have some initial value! Kotlin's not like Java that way, where things can be left unassigned and default to a value.
So you just have to assign a value:
var y = 1
get() = 4
Now your backing field has a value so the compiler's happy. You never actually read from it, so it's useless, and that's a good sign you don't need a var at all!
Have a look at the properties documentation, it explains all this stuff (and some other things about visibility etc) but hopefully that makes sense, and you can see why your example is actually a bit strange and something you'd avoid.
val y = 4
is a val, which means it's read-only. The value you're initialising it with, 4, is stored in a backing field. A bit of memory where the value of that variable is stored.var y = 4
is a var, which means you can write to it. Again, there's a backing field storing the current value - it's just that you can change it now.This is probably all stuff you're used to - but Kotlin also allows you to define getter and setter functions, depending on whether it's a
val
(getter only) orvar
. In reality, default getters and setters already exist - they just read from and write to the backing field. If you don't define your own, it just uses those.val y get() = 4
is a val, which means it's read-only. Because you've added a getter function, the4
value isn't actually stored in a backing field - so Kotlin doesn't create one! There's nothing to initialise with a value.var y get() = 4
is a var, so you have the ability to set it. You haven't defined a setter function here, so it's using the implicit default one, which writes to the backing field.And that's where your problem is - Kotlin won't create a backing field if it doesn't need one:
(It's not a good example because generally you wouldn't have a fixed value with a setter, because what's the point? But you could have, say, a getter/setter pair that stores and reads from a map or something, which doesn't require a backing field since it's getting and storing the data elsewhere)
So when you do
var y get() = 4
you're effectively doing this:and that's creating a backing field through the setter. And that field needs to have some initial value! Kotlin's not like Java that way, where things can be left unassigned and default to a value.
So you just have to assign a value:
Now your backing field has a value so the compiler's happy. You never actually read from it, so it's useless, and that's a good sign you don't need a
var
at all!Have a look at the properties documentation, it explains all this stuff (and some other things about visibility etc) but hopefully that makes sense, and you can see why your example is actually a bit strange and something you'd avoid.