Kotlin的部分班级代表团

时间:2015-06-17 21:08:31

标签: multiple-inheritance delegation kotlin

如何在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()

2 个答案:

答案 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() {

}

修改:单独回答:https://stackoverflow.com/a/30914383/615306