使用 interface
声明一个接口, 接口里可以声明抽象方法, 也可以有方法实现. 跟抽象
类的区别是, 接口不能保存状态(没有 backing field), 可以声明属性但是不能初始化它,
得是抽象属性, 或提供 getter setter 方法. 又因为无法保存状态, 所以 setter 没什么
意义. 所以若不是抽象属性, 一般用 val 并提供 getter.
属性重写可以直接用主构造函数中使用 override
, 也可以
interface Ia {
val va: Int // 抽象属性
var vb: Int // 抽象属性
val vc get() = 1 // 提供 getter 的属性
var vd
get() = 2
set(value) {
println("如果子类重写了 vd 属性, 这里不会执行")
println("没有 backing field, 不能保存状态, 这么做基本上没意义")
}
fun a() // 抽象方法
fun b() = println("b") // 具体方法, 不用 override
}
class A(override val va: Int, override var vb: Int) : Ia {
// vc 和 vc 都有实现代码, 所以不必须重写
// 我们重写个 vd 吧
override var vd = 2222
override fun a() {
println("a")
}
// 可以重写, 也可以不重写
override fun b() {
super.b()
println("A b")
}
}
fun main(args: Array<String>) {
val objA = A(11, 22)
println(objA.va) // 11
println(objA.vb) // 22
println(objA.vc) // 1
println(objA.vd) // 2222
objA.vd = 3 // 如果没重写 vd, 是无法保存状态的, 但是重写了.
println(objA.vd) // 3
objA.a() // a
objA.b() // b 换行 A b
}
接口继承
接口可以继承其他接口.
interface Ib {
val b: Int
}
interface Ic: Ib {
val c: Int
override val b: Int
get() = c * 2
}
// 属性 b 已经有实现代码了, 所以不用重写
class D(override val c: Int, val d: Int) : Ic {
}
解决重写冲突问题
// 解决冲突
interface Ie {
fun f() = println("Ie")
}
interface If {
fun f() = println("If")
}
class Cg: Ie, If {
// 必须重写了, 因为不知道要调用哪个 f()
override fun f() {
println("Cg")
// 需要指定调用哪个父类接口的实现方法可以这样
super<Ie>.f()
super<If>.f()
}
}