例如:
class A {
var value: String
get() = "value"
set(value) { println(value) }
}
class B {
val a = A()
var value = a.value
}
fun main(args: Array<String>) {
B().value = "new value"
}
B.value
仅用A.value.get
初始化,因此在A.value.set
函数中分配期间当然不会调用main
,因此不会将消息打印到控制台。
我要寻找的是一种语法,该语法将允许根据相同类型的不同对象的属性将get
和set
函数转发到新变量。
我设法实现了这种委托,但是它依赖于kotlin-reflect库(调用getter
和setter
),我想避免这种情况:
import kotlin.reflect.KProperty
import kotlin.reflect.KMutableProperty
class Forward<T> (private val originalProperty: KProperty<T>){
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
return originalProperty.getter.call()
}
}
class ForwardMutable<T> (private val originalProperty: KMutableProperty<T>){
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
originalProperty.setter.call(value)
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
return originalProperty.getter.call()
}
}
fun <T> forward(originalProperty: KProperty<T>) = Forward(originalProperty)
fun <T> forward(originalProperty: KMutableProperty<T>) = ForwardMutable(originalProperty)
class A {
var value: String
get() = "value"
set(value) { println(value) }
}
class B {
val a = A()
var value by forward(a::value)
}
fun main(args: Array<String>) {
B().value = "new value" // calls A.value.setter
}
是否没有用于此目的的内置委托?如果没有,如何避免kotlin-reflect
依赖性?
答案 0 :(得分:0)
如果thisRef
必须与Any
一样通用,那么我认为您不能在没有反射的情况下访问其属性。
如果您愿意引入其他接口,则可以按照以下方式做一些事情:(kotlin.reflect
仍然有导入依赖项,但是Delegate
API要求这样做)>
import kotlin.reflect.KProperty
interface HasA<T> {
val a: ValueAccessor<T>
}
interface ValueAccessor<T> {
var value: T
}
class ForwardMutable<T> {
operator fun setValue(thisRef: HasA<T>, property: KProperty<*>, value: T) {
thisRef.a.value = value
}
operator fun getValue(thisRef: HasA<T>, property: KProperty<*>): T {
return thisRef.a.value
}
}
class A : ValueAccessor<String> {
override var value: String = "value"
}
class B : HasA<String> {
override val a = A()
var value by ForwardMutable<String>()
}
fun main(args: Array<String>) {
val b = B()
b.value = "new value" // calls A.value.setter
print(b.value)
}
答案 1 :(得分:0)
也许我误会了一些东西,但是,如果您能够提取要委托给内部实例的变量的接口,那为什么不只使用委托呢?
interface SomethingWithValues{
var value: String
var value2: String
var value3: String
}
class A : SomethingWithValues{
override var value: String = "value"
set(value) {print(value)}
override var value2: String = "value2"
set(value) {print(value)}
override var value3: String = "value3"
set(value) {print(value)}
}
class B(val a:A = A()): SomethingWithValues by a
fun main(args: Array<String>) {
val b = B()
b.value = "new value"
b.value2 = "new value2"
b.value3 = "new value3"
}