Kotlin:与Swift中的属性包装器相当

4
什么是Kotlin的属性包装器的等效物:
@propertyWrapper
struct Foo {

    var wrappedValue: String {
        get {
            return "Test
        }
    }

}

@Foo var test: String


3
我不知道答案,但是这个问题表明你正在尝试通过用 Kotlin 术语替换 Swift 术语来将一个 Swift 应用程序移植到 Kotlin。如果是这样,你将会遇到很大的困难。你最终会得到可怕的伪 Swift Kotlin 代码,它既不像 Swift 的对应代码,也不是其他 Kotlin 开发者会认可或愿意使用的良好 Kotlin 代码。 - Alexander
2
我还没有学习Swift,但是从快速浏览有关Swift属性包装器的教程来看,它们似乎与Kotlin的委托属性非常相似。但是,一些更简单的属性包装器功能可以直接在Kotlin中使用自定义getter和setter实现。 - Tenfour04
2个回答

3
在Kotlin中,有几个选项来添加自定义属性行为,可以在 文档 中查看。基本上有两个选项:自定义setter/getter和委托属性
以下是在Kotlin中可能与Java不同的一些事情:
  • 属性是valvarval类似于Java中的final,只能赋值一次,而var可以重新赋值。

  • 两种类型都可以具有自定义getter。 var可以具有自定义setter。

  • 如果要使用支持字段,Kotlin会为您提供一个支持字段。只需在setter或getter中使用关键字field即可。

  • Kotlin属性没有隐式默认值。必须在构造函数中初始化(或通过init块)或在声明之后通过=进行初始化。

  • 某些属性实际上是计算属性,不存储任何内容。在这种情况下,没有支持的field,也不需要(或允许)初始化程序。

例如:
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 }
}

2
Kotlin的属性getter/setter不足以实现属性包装器(它在管理属性存储方式的代码和根据https://docs.swift.org/swift-book/LanguageGuide/Properties.html定义属性的代码之间添加了一层分离)。委托属性是在Kotlin中实现相同功能的机制。
对于问题中的只读示例,属性包装器并没有太多意义,在Kotlin中,您只需要编写以下代码即可(无需使用委托):
val test = "Test"

这个例子更适合展示Kotlin中的“等效”写法,来源于https://docs.swift.org/swift-book/LanguageGuide/Properties.html
@propertyWrapper
struct TwelveOrLess {
    private var number = 0
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}

@TwelveOrLess var height: Int


以上可以用 Kotlin 实现如下:
var twelveOrLess: Int = 0
    set(value) {
        field = value.coerceAtMost(12)
    }

var height by ::twelveOrLess

更复杂的示例可以使用类来委托:
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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接