Mic*_*ael 7 kotlin sealed-class
假设我有一个sealed class这样的层次结构:
sealed class A {
abstract val x: Int
abstract fun copyX(x1: Int): A
}
data class A1(override val x: Int, val s1: String) : A() {
override fun copyX(x1: Int): A {
return this.copy(x = x1)
}
}
data class A2(override val x: Int, val s2: String) : A() {
override fun copyX(x1: Int): A {
return this.copy(x = x1)
}
}
Run Code Online (Sandbox Code Playgroud)
所有的数据类有现场x,并应提供方法copyX(x1: Int)来复制所有字段,但x并覆盖x有x1。例如,
fun foo(a: A): A { a.copyX(100) }
Run Code Online (Sandbox Code Playgroud)
上面的定义可能有用,但是copyX在所有数据类中重复似乎很笨拙。您如何建议消除这种重复copyX?
首先,您可以将其实现copyX为扩展(甚至A成员),以便将代码集中在一个地方,并避免至少copyX在密封的类子类型中复制函数:
sealed class A {
abstract val x: Int
}
fun A.copyX(x1: Int): A = when (this) {
is A1 -> copy(x = x1)
is A2 -> copy(x = x1)
}
data class A1(override val x: Int, val s1: String) : A()
data class A2(override val x: Int, val s2: String) : A()
Run Code Online (Sandbox Code Playgroud)
如果您有很多密封的子类型,并且所有子类型都是data类或具有一个copy函数,则也可以使用反射来泛型地复制它们。对于这一点,你需要获得primaryConstructor或命名的函数copy从KClass,然后填写为调用的参数,寻找x由名称参数,并把该x1值它,并把从获得的值component1(),component2()等来电或保留默认其他参数的值。它看起来像这样:
fun A.copyX(x1: Int): A {
val copyFunction = this::class.memberFunctions.single { it.name == "copy" }
val args = mapOf(
copyFunction.instanceParameter!! to this,
copyFunction.parameters.single { it.name == "x" } to x1
)
return copyFunction.callBy(args) as A
}
Run Code Online (Sandbox Code Playgroud)
之所以callBy可行,是因为省略了可选参数。
请注意,它需要依赖kotlin-reflect并且只能与Kotlin / JVM一起使用。同样,反射也有一些性能开销,因此不适合于性能关键的代码。您可以改为使用Java反射(this::class.java,getMethod(...))(这会更冗长)并缓存反射实体来优化此效果。
| 归档时间: |
|
| 查看次数: |
50 次 |
| 最近记录: |