Getters and Setters in Kotlin
KotlinGetter SetterKotlin Problem Overview
In Java, for example, I can write getters on my own (generated by IDE) or use Annotations like @Getter in lombok - which was pretty simple.
Kotlin however has getters and setters by default. But I can't understand how to use them.
I want to make it, lets say - similar to Java:
private val isEmpty: String
get() = this.toString() //making this thing public rises an error: Getter visibility must be the same as property visibility.
So how do getters work?
Kotlin Solutions
Solution 1 - Kotlin
Getters and setters are auto-generated in Kotlin. If you write:
val isEmpty: Boolean
It is equal to the following Java code:
private final Boolean isEmpty;
public Boolean isEmpty() {
return isEmpty;
}
In your case the private access modifier is redundant - isEmpty is private by default and can be accessed only by a getter. When you try to get your object's isEmpty property you call the get method in real. For more understanding of getters/setters in Kotlin: the two code samples below are equal:
var someProperty: String = "defaultValue"
and
var someProperty: String = "defaultValue"
get() = field
set(value) { field = value }
Also I want to point out that this
in a getter is not your property - it's the class instance. If you want to get access to the field's value in a getter or setter you can use the reserved word field
for it:
val isEmpty: Boolean
get() = field
If you only want to have a get method in public access - you can write this code:
var isEmpty: Boolean
private set
due to the private modifier near the set accessor you can set this value only in methods inside your object.
Solution 2 - Kotlin
The rules about property accessors visibility modifiers are the following:
-
Getter visibility of
var
andval
property should be exactly the same to the visibility of the property, thus you can only explicitly duplicate the property modifier, but it is redundant:protected val x: Int protected get() = 0 // No need in `protected` here.
-
Setter visibility of
var
property should be the same or less permissive than the property visibility:protected var x: Int get() = 0 private set(x: Int) { } // Only `private` and `protected` are allowed.
In Kotlin, properties are always accessed through getter and setter, thus there's no need in making a property private
with public
accessors like in Java -- its backing field (if present) is already private. So, visibility modifiers on property accessors are only used to make setter visibility less permissive:
-
For a property with backing field and default accessors:
var x = 0 // `public` by default private set
-
For a property without backing field:
var x: Int // `public` by default get() = 0 protected set(value: Int) { }
Solution 3 - Kotlin
-
Example default
setter
andgetter
for propertyfirstName
in Kotlinclass Person { var firstName: String = "" get() = field // field here ~
this.firstName
in Java or normally_firstName
is C# set(value) { field = value }}
Using
val p = Person()
p.firstName = "A" // access setter
println(p.firstName) // access getter (output:A)
IF your setter
or getter
is exactly same above, you can remove it because it is unnecessary
-
Example custom setter and getter.
const val PREFIX = "[ABC]"
class Person {
// set: if value set to first name have length < 1 => throw error else add prefix "ABC" to the name // get: if name is not empty -> trim for remove whitespace and add '.' else return default name var lastName: String = "" get() { if (!field.isEmpty()) { return field.trim() + "." } return field } set(value) { if (value.length > 1) { field = PREFIX + value } else { throw IllegalArgumentException("Last name too short") } }
}
Using
val p = Person()
p.lastName = "DE " // input with many white space
println(p.lastName) // output:[ABC]DE.
p.lastName = "D" // IllegalArgumentException since name length < 1
More
I start learn Kotlin from Java so I am confusing about field
and property
because in Java there is no property
.
After some search, I see field
and property
in Kotlin look like C# (https://stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property)
Here is some relevant post which talk about field
and property
in Java and Kotlin.
https://stackoverflow.com/questions/2963243/does-java-have-something-similar-to-c-sharp-properties
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531
Correct me if I am wrong. Hope it help
Solution 4 - Kotlin
Getter in kotlin is by default public, but you can set the setter to private and set the value by using one method inside a class. Like this.
/**
* Created by leo on 17/06/17.*/
package foo
class Person() {
var name: String = "defaultValue"
private set
fun foo(bar: String) {
name = bar // name can be set here
}
}
fun main(args: Array<String>) {
var p = Person()
println("Name of the person is ${p.name}")
p.foo("Jhon Doe")
println("Name of the person is ${p.name}")
}
Solution 5 - Kotlin
You can see this tutorial for more info:
[Yet Another Kotlin Tutorial for Android Developers][1]
[1]: https://codete.com/blog/yet-another-kotlin-tutorial-android-developers-part-1/ "Yet Another Kotlin Tutorial for Android Developers"
> Properties
>
> In Kotlin world, classes cannot have fields, just properties. var
> keyword tells us the property is mutable, in contrast to val. Let’s
> see an example:
>
> class Contact(var number: String) {
>
> var firstName: String? = null
> var lastName: String? = null
> private val hasPrefix : Boolean
> get() = number.startsWith("+")
>
> }
> There is not much code, but lots of things are happening behind the
> scenes. We will go through it step by step. First of all, we created a
> public final class Contact.
>
> This is the primary rule we have to face: if not specified otherwise,
> classes are public and final by default (by the way, the same is for
> class methods). If you want to inherit from class, mark it with open
> keyword.
Solution 6 - Kotlin
If you have a Var then you can:
var property: String = "defVal"
get() = field
set(value) { field = value }
But in the case of Val, you can not set it once assigned, so there won't be a setter block:
val property: String = "defVal"
get() = field
or if you don't want setter then:
val property: String = "defVal"
private set
Solution 7 - Kotlin
Here's a practical, real world example of a Kotlin getter and setter (See more details here):
// Custom Getter
val friendlyDescription get(): String {
val isNeighborhood = district != null
var description = if (isNeighborhood) "Neighborhood" else "City"
description += " in"
if (isNeighborhood) {
description += " $city,"
}
province?.let {
if (it.isNotEmpty()) {
description += " $it,"
}
}
description += " $country"
return description
}
print(myLocation.friendlyDescription) // "Neighborhood in Denver, Colorado, United States"
// Custom Setter
enum class SearchResultType {
HISTORY, SAVED, BASIC
}
private lateinit var resultTypeString: String
var resultType: SearchResultType
get() {
return enumValueOf(resultTypeString)
}
set(value) {
resultTypeString = value.toString()
}
result.resultType = SearchResultType.HISTORY
print(result.resultTypeString) // "HISTORY"