'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 or var. val is like final in Java, can only be assigned once, var can be reassigned.

  • Both kinds can have custom getters. vars 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