The following kotlin code
val nameHash get() = name.hashCode()
can be compiled into java as follows
public final int getNameHash() {
return name.hashCode();
}
and the property nameHash disapears. However when the val is changed to var, the compiler says "Property must be initialized" What is the deeper difference between var and val?
CodePudding user response:
How does kotlin compiler know whether a val should be a property or a function
As far as the Kotlin language is concerned, val
denotes properties, never functions. However, there is a difference between these two property declarations:
val nameHash get() = name.hashCode()
var nameHash get() = name.hashCode()
And that is that the first property does not have a backing field. Properties with backing fields must be initialised one way or another, for example:
var nameHash = 0 // for example
get() = name.hashCode()
And this is why your code with var
didn't compile.
If you are asking for the situations when a backing field is generated for a Kotlin property, they are listed in the spec:
However, the backing field is created for a property only in the following cases
- A property has no custom accessors;
- A property has a default accessor;
- A property has a custom accessor, and it uses
field
property;- A mutable property has a custom getter or setter, but not both.
These are the cases where your property needs a backing field. Your var nameHash
satisfies that last case, because it is a "mutable property". If you use val
instead, it is not a mutable property anymore and doesn't satisfy any of those cases.
Intuitively, a mutable property without setter needs a backing field because one must need to be able to set the property. How can you set it when it has no setter? Well, the Kotlin compiler solves the problem by generating a backing field and just sets the backing field instead.
CodePudding user response:
Property is a functions set()
& get()
. Read-only properties implement only the get()
function, but still, it's a function, so everything written in the property will be executed every time it's called.
In Kotlin, keywords: val
is the same as the read-only property, meaning it's required to implement only get()
function. When you put var
keyword, compiler expects you to implement both get()
& set()
functions.
So, compile error there because your property missing set()
function that is usually needed to store a value (or as the compiler says: must be initialized).
CodePudding user response:
The error message is a little confusing in this case. The difference between val
and var
is that val
means there is a getter while var
means there is a getter and a setter. To fix your code you need to add an implementation for the setter:
var nameHash
get() = name.hashCode()
set(hash: Int) { ... }
Although, in this case I don't think it makes too much sense. We can't set the hash code value of the name
.