2017-04-16 18 views
2

我现在宣布这样的特性:如何实现从某个特定源直接在Kotlin中设置的属性?

class Foo(val base : FooBase){ 
    var _number: Int? = null 

    override var number: Int 
     get() = _number ?: base.number 
     set(value) {_number = value} 
} 

不过,我有很多像这样的性质,导致相当多的重复代码。有没有办法避免这种情况?我明白,财产代表团是一种方式来做到这一点,但我不确定如何正确实施ReadWriteProperty<...>。如果我应该使用它,我该如何使用“财产”价值?

回答

2

以下是对Yoav Sternberg的回答进行的性能改进。正如你看到的,它是不太通用,但它避免了整数自动装箱:

class IntUninitializedProperty(private val getter:() -> Int) { 
    private var isInitialised = false 
    private var value: Int = 0 

    fun getValue(thisRef: Any?, property: KProperty<*>): Int = if(isInitialised) value else getter() 

    fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { 
     this.value = value 
     isInitialised = true 
    } 
} 
6

你需要创建一个扩展ReadWriteProperty提供该功能的类(代码示例是基于不安全的懒惰实现)

class UninitializedProperty<T>(private val getter:() -> T) : ReadWriteProperty<Any?, T> { 
    var _value: Any? = UNINITIALIZED_VALUE 

    @Suppress("UNCHECKED_CAST") 
    override fun getValue(thisRef: Any?, property: KProperty<*>): T = if(_value === UNINITIALIZED_VALUE) getter() else _value as T 

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { 
     _value = value 
    } 

    private object UNINITIALIZED_VALUE 
} 

其次,为了保持恒定符合标准的代表像lazy定义一个辅助方法:

fun <T> uninitialized(getter:() -> T): ReadWriteProperty<Any?, T> = UninitializedProperty(getter) 

现在你可以使用它:

class Foo(val base: FooBase) { 
    override var number: Int by uninitialized { base.number } 
} 

说明:该类不是线程安全的。

查看official documentation了解更多关于代表团的信息。

+0

我建议把'私有对象UNINITIALIZED_VALUE'内'UninitializedProperty',而不是沿着它 – voddan

+0

的实施有一个bug。如果它是用'null'初始化呢?为了解决这个问题,你需要比较'_value'和'UNINITIALIZED_VALUE',而不是'null'。 – voddan

+0

@voddan修好了,谢谢。 –

相关问题