Field accessors in Java
In Java world, we are so accustomed to writing getters and setters for our fields, that the advice by Effective Java Item 14: In public classes, use accessor methods, not public fields sort of goes without saying. All major IDEs help us here: they generate getters and setters, so that it is not that hard to produce a class like this:
Most of the lines in this class are pure boilerplate code.
Getting rid of field/get/set triples
In Kotlin, there's no way to declare a field. All you have is properties. Read/write properties are declared with the
var keyword, and read-only ones – with
val keyword. Thus, the class above can be rewritten as follows:
(For even better option look here).
To use a property, one simply refers to it by name, as if it were a field in Java:
Declaring properties and accessors
The full syntax for a mutable property declaration is as follows:
The initializer, getter and setter are optional. Property type is optional if it can be inferred from the initializer or from the base class member being overridden .
Note that types are not inferred for properties exposed as parts of the public API, i.e. public and protected, because changing the initializer may cause an unintentional change in the public API then. For example
The full syntax of an immutable property declaration differs from a mutable one in two ways: it starts with
val instead of
var and does not allow a setter:
We can write custom accessors, very much like ordinary functions, right inside a property declaration. Here's an example of a custom getter:
Since this property is purely derived from others, the compiler will not generate a backing field for it.
A custom setter looks like this:
As we mentioned above, some properties have backing fields, i.e. from the client's point of view, a property is a pair of accessors (or just one getter), but physically the accessors may read and write data from/to a real field. One can not declare a field explicitly in Kotlin, the compiler figures it out for us.
In the simple cases, when we do not provide custom accessor implementations, it is obvious that a property must have a backing field, otherwise what should the default accessors do in the following case?
But when there is a custom accessor, it may or may not rely on a backing field.
To access a backing field of a property
x, one says
$x (the dollar sign cannot be used as a part of an identifier in Kotlin):
$counter field can be accessed only from inside the class where the
counter property is defined.
The compiler looks at the accessors' bodies, and if they use the backing field (or the accessor implementation is left by default), a backing field is generated, otherwise it is not.
For example, in the following case there will be no backing field:
The backing field is not needed because the only accessor does not refer to it.
What if I want to do ... ?
If you want to do something that does not fit into this "implicit backing field" scheme, you can always fall back to having a "backing property":
In all respects, this is just the same as in Java since access to private properties with default getters and setters is optimized so that no function call overhead is introduced.
Best practices related to this feature
J. Bloch. Effective Java Second Edition
Item 14: In public classes, use accessor methods, not public fields
See also: JavaBeans
Similar features in other languages
Java IDEs generate accessors automatically.
For Java, there's Project Lombok : the syntax for properties is based on Java annotations.
In C#, Groovy Beans and Gosu one still writes getters and setters alongside their backing fields that are declared explicitly, although the access looks like property access. Scala does not distinguish between a field and a property, but to customize a setter one needs to write a separate function named by convention.