如何在Kotlin中部分委派方法/字段?
具体来说:在这里,我尝试从接口User
继承课程TraitA
,并在包装器marked: Boolean
中实现字段StateA
。那会清理User
实现,因为marked
只是一个状态字段。请注意,TraitA
不能成为一个类,因为我想使用几个这样的接口:User() : TraitA by StateA, TraitB by StateB, ..
/* does not compile (Kotlin M12) */
interface TraitA {
var marked: Boolean
fun doStaffWithMarked() // must be overridable
}
class StateA() : TraitA {
override var marked = false
}
class User() : TraitA by StateA(){
override fum doStaffWithMarked() {
//...all fancy logic here...
}
}
另一种方法是在一个地方实现所有:
class User() : TraitA{
override var marked = false // ugly code
override fum doStaffWithMarked() {
//...
}
}
是否有一种方法/模式可以通过简单且尽可能少的代码解决该问题?代码/字节码生成不适合我。
更新
我对此并不十分清楚,但请注意每doStaffWithMarked()
User
唯一 。
所以我可能会建议一个半坏的'运行时断言的解决方案:
interface TraitA {
var marked: Boolean
/* must be overridden */
fun doStaffWithMarked() = throw UnsupportedOperationException()
}
class StateA() : TraitA {
override var marked = false
}
class User() : TraitA by StateA() {
override fum doStaffWithMarked() {
//...all fancy logic here...
}
}
问题仍然存在,因为一个非常好的解决方案会在编译时检查doStaffWithMarked()
。
答案 0 :(得分:10)
将TraitA
拆分为两个接口,然后委托一个接口并实现另一个接口:
interface TraitA {
var marked: Boolean
}
interface TraitAPlus : TraitA {
fun isMarked(): Boolean
}
class StateA() : TraitA {
override var marked = false
}
class User() : TraitA by StateA(), TraitAPlus {
override fun isMarked(): Boolean {
return marked
}
}
答案 1 :(得分:1)
这是一个仅从StateA
继承而不是委托的版本,但这不是很好:
interface TraitA {
var marked: Boolean
fun isMarked(): Boolean
}
abstract class StateA() : TraitA {
override var marked = false
}
class User() : TraitA, StateA() {
override fun isMarked(): Boolean {
return marked
}
}
这是一种有点不同寻常的方法,我将TraitA
委托给StateA
的匿名实例
class User() : TraitA by object : StateA() {
override fun isMarked(): Boolean {
return marked
}
} {
}
说实话,我宁愿重新考虑类层次结构的设计。特别是,您可以将方法实现放在接口中(但不是属性值),因此如果isMarked()
仅依赖于marked
,您可以直接将实现放在TraitA
中。然后你的代码变成:
interface TraitA {
var marked: Boolean
fun isMarked(): Boolean {
return marked
}
}
class StateA() : TraitA {
override var marked = false
}
class User() : TraitA by StateA() {
}