'Kotlin: Equivalent of property wrappers from Swift
What is the equivalent property wrappers for Kotlin:
@propertyWrapper
struct Foo {
var wrappedValue: String {
get {
return "Test
}
}
}
@Foo var test: String
Solution 1:[1]
The accepted answer doesn't answer the question imo. Kotlin's property getters/setters are not sufficient to implement a property wrapper (which adds a layer of separation between code that manages how a property is stored and the code that defines a property according to https://docs.swift.org/swift-book/LanguageGuide/Properties.html). Delegated properties are the mechanism to achieve the same in Kotlin.
For the read-only example in the question, property wrappers don't really make sense, in Kotlin you would simply write (no need for delegates):
val test = "Test"
The example from https://docs.swift.org/swift-book/LanguageGuide/Properties.html is better suited to show the "equivalent" in Kotlin.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
@TwelveOrLess var height: Int
Above could be implemented like this in Kotlin:
var twelveOrLess: Int = 0
set(value) {
field = value.coerceAtMost(12)
}
var height by ::twelveOrLess
For more complex examples you could use a class to delegate to:
class TwelveOrLess(private val initValue: Int = 0) {
private var number = initValue
operator fun getValue(thisRef: Any?, property: KProperty<*>)= number
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
number = value.coerceAtMost(12)
}
}
var height by TwelveOrLess()
Solution 2:[2]
In Kotlin, there are several options from the documentation for how to add custom behavior to properties. There are basically two options: custom setters / getters, and Delegated Properties.
Some things that may be different in Kotlin:
Properties are
val
orvar
.val
is likefinal
in Java, can only be assigned once,var
can be reassigned.Both kinds can have custom getters.
var
s can have custom setters.If you want a backing field, Kotlin provides one for you. Just use the keyword
field
in a setter or getter.Kotlin properties do not have an implicit default value. You must initialize in the constructor (or via an
init
block) or at the declaration after an=
.Some properties are actually computed and don't actually store anything. In this case, there is no backing
field
, and no initializer is required (or allowed).
Example:
class Dog {
// Must have initial value, default getter and setter. Value can come from constructor.
val isNice: Boolean = true
set(value) { ... } // This produces an error, no setters on vals
// Must have initial value, default getter
var age: Int = 0
set(value) { if (value >= 0) field = value }
// Value is just computed, has no field and cannot have initial value
var ageInDogYears: Int
get() = age * 7
set(value) { age = value / 7 }
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Emanuel Moecklin |
Solution 2 | Adam |