我經常有一個具有在實體化時初始化的屬性的類,例如
class C {
var x = 10
var y = v * 2 // v is some variable
}
val c = C()
然后 的 屬性c被更改,稍后我需要重新初始化屬性(這又c.x是和,其中的值可能已更改)。10c.yv*2v
我目前的方法是使用虛擬值(或者使用lateinit和型別注釋)初始化屬性,并在額外的函式中分配所需的值,ini例如
class C {
var x = 0
var y = 0
init {
ini()
}
fun ini() {
x = 10
y = v * 2
}
}
然后我打電話c.ini()重新初始化。
有沒有更好(更簡潔)的方法來避免虛擬值?
請注意,在 JavaScript 中我可以簡單地撰寫
class C {
constructor() {
this.ini()
}
ini() {
this.x = 10
this.y = v * 2
}
}
uj5u.com熱心網友回復:
你現在所做的一切都很好。我不會改變它。
如果您想避免 的占位符值0,或者如果屬性的型別沒有有意義的占位符值,您可以將初始值存盤在私有 lambda 中:
class C {
private val xInit = { 10 }
private val yInit = { v * 2 }
var x = xInit()
var y = yInit()
fun reset() {
x = xInit()
y = yInit()
}
}
如果你真的想減少樣板,我只能想到這個依賴反射的相當hacky和緩慢的解決方案。如果不需要經常重置實體,并且您有很多具有可重置屬性的類,并且您只是討厭撰寫樣板方法,這可能是有用的。reset
class Resettable<T>(val supplier: () -> T) {
var wrapped = supplier()
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
return wrapped
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
wrapped = value
}
fun reset() {
wrapped = supplier()
}
}
fun <T: Any> T.reset() {
// look for properties delegated with Resettable
this::class.memberProperties.mapNotNull {
it.isAccessible = true
(it as KProperty1<T, *>).getDelegate(this)
}.filterIsInstance<Resettable<*>>().forEach {
it.reset()
}
}
現在你只需要這樣做:
var v = 10
class C {
var x by Resettable { 10 }
var y by Resettable { v * 2 }
}
fun main() {
val x = C()
println(x.y) // 20
v = 20
x.reset()
println(x.y) // 40
v = 40
x.reset()
println(x.y) // 80
}
請注意,第一次reset呼叫將加載所有 kotlin 反射類,并且會花費大量時間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/411650.html
標籤:
