您可以像这样实现自己的委托:
private val maps = WeakHashMap<Any, MutableMap<String, Any>>()
object LateVal {
fun bindValue(any: Any, propertyName: String, value: Any) {
val map = maps.getOrPut(any) { mutableMapOf<String, Any>() }
if (map[propertyName] != null) {
throw RuntimeException("Value is initialized")
}
map[propertyName] = value
}
fun <T> lateValDelegate(): MyProperty<T> {
return MyProperty<T>(maps)
}
class MyProperty<T>(private val maps: WeakHashMap<Any, MutableMap<String, Any>>) : ReadOnlyProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
val ret = maps[thisRef]?.get(property.name)
return (ret as? T) ?: throw RuntimeException("Value isn't initialized")
}
}
}
fun <T> lateValDelegate(): LateVal.MyProperty<T> {
return LateVal.MyProperty<T>(maps)
}
fun Any.bindValue(propertyName: String, value: Any) {
LateVal.bindValue(this, propertyName, value)
}
之后,您可以按如下方式使用它:
class Hat(val name: String = "casquette") {
override fun toString(): String {
return name
}
}
class Human {
private val hat by lateValDelegate<Hat>()
fun setHat(h: Hat) {
this.bindValue(::hat.name, h)
}
fun printHat() {
println(hat)
}
}
fun main(args: Array<String>) {
val human = Human()
human.setHat(Hat())
human.printHat()
}
如果您在初始化之前尝试访问值,您将得到异常以及尝试重新分配新值时。
此外,您可以编写 DSL 以使其可读。
object to
infix fun Any.assigned(t: to) = this
infix fun Any.property(property: KProperty<*>) = Pair<Any, KProperty<*>>(this, property)
infix fun Pair<Any, KProperty<*>>.of(any: Any) = LateVal.bindValue(any, this.second.name, this.first)
然后这样称呼它:
fun setHat(h: Hat) {
h assigned to property ::hat of this
}