在很多实际业务中很有可能会面对一个问题:一个类的多继承.回手翻资料所有文档档案都会告诉你Java/Kotlin是不能多继承的,而多继承是实现在C++语言之中,由此C++也引出了一个所谓的经典的钻石问题,相关背景此处不再多述,有兴趣者可以翻阅相关资料.
好的,在Kotlin中要实现多继承那么我们就要借用它的多实现特性:
一. 接口实现多继承
interface Tiger{
val name: String
fun climbTree()
fun colour() = "yellow and white"
}
interface Lion{
fun eatMeat()
fun colour() = "yellow"
}
class Tigon(override val name: String):Tiger,Lion{
override fun climbTree() {
println("it can climb tree")
}
override fun eatMeat() {
println("it can eat meat")
}
override fun colour(): String { // here todo custom return value
return super<Lion>.colour()
}
}
Kotlin的super关键字可以指定继承那个父类接口的方法,这也是Java/Kotlin常用的方式;
执行测试结果:"yellow"
fun main() {
println(Tigon("虎狮").colour())
}
二. 内部类实现多继承
open class Tiger(val name: String = ""){
fun climbTree()="i can climb tree"
fun colour() = "yellow and white"
}
open class Lion{
fun eatMeat()="i can eat meat"
fun colour() = "yellow"
}
class Tigon{
fun climbTree()= Tiger1().climbTree()
fun eatMeat() = Lion1().eatMeat()
fun colour() = Tiger1().colour()
private inner class Tiger1:Tiger()
private inner class Lion1:Lion()
}
事实上,我们可以在一个类的内部定义多个内部类,而内部类与外部类的信息是相互独立的,并且我们可以用private关键字去修饰内部类,使得其他类都不能访问内部类,具有非常好的封装性.
执行测试结果:"yellow and white"
fun main() {
println(Tigon().colour())
}
三. 委托实现多继承
interface ClimbTree{
fun climbTree(): String
fun colour(): String
}
interface EatMeat{
fun eatMeat(): String
fun colour(): String
}
open class Tiger: ClimbTree{
override fun colour() = "yellow and white"
override fun climbTree() = "i can climb tree"
}
open class Lion: EatMeat{
override fun colour() = "yellow"
override fun eatMeat() = "i can eat meat"
}
class Tigon(val tiger: Tiger,val lion: Lion):ClimbTree by tiger,EatMeat by lion {
override fun colour() = tiger.colour()
}
委托是Kotlin新引入的语法,如果您是一名C#开发者,您极有可能熟悉关键字delegate,他是一种特殊的类型,用于方法事件委托,在Kotlin中可以通过by关键字实现委托.例如经常会用到的延迟属性 by lazy ,除了这种内置行为外,还提供了一种可观察属性的行为,这就很像我们Java中所说的观察者模式.以后有条件我会单独开一篇,利用委托来改善观察者模式.
执行测试结果:"i can climb tree"
"yellow and white"
fun main() {
val tiger = Tiger()
val lion = Lion()
val tigon = Tigon(tiger,lion)
println(tigon.climbTree())
println(tigon.colour())
}
事实上,当使用委托来实现多继承就必须强制覆写委托类中的相同名称接口,很多人会疑问这跟接口实现多继承极为相似,而且并没有简单多少东西;也似乎也跟组合相像,其实委托在我目前看来至少有两处优点:
1. 接口是不能实现复杂逻辑的,且不赞成在接口中实现复杂的业务逻辑,上述委托虽说也是接口委托,但它是有具体的类去实 现方法逻辑;
2. 当我们需要继承一个类A,委托对象是B,在具体调用的时候并不是像组合一样A.B.methodB,而是直接调用A.methodB,这 能更加直观的表达A所拥有的methodB的行为,故所谓所述观察者模式特征A类的methodB实际由B类methodB来完成.