интерфейс
Интерфейсы в Kotlin очень похожи на Java 8. Они могут содержать объявления абстрактных методов, а также реализации методов. В отличие от абстрактных классов, интерфейсы не могут хранить состояние. У них могут быть свойства, но эти свойства должны быть абстрактными или предоставлять реализации средств доступа.
Для определения интерфейса используйте ключевое слово interface:
interface MyInterface {
fun bar()
fun foo() {
// 函数体是可选的
}
}
Реализация интерфейса
Класс или объект могут реализовывать один или несколько интерфейсов:
class Child : MyInterface {
override fun bar() {
...
}
}
свойства в интерфейсе
Свойство, объявленное в интерфейсе, может быть абстрактным, и если оно не является абстрактным, для него должен быть реализован метод доступа. Свойства в интерфейсе не могут иметь резервных полей, поэтому объявленные в интерфейсе аксессоры не могут на них ссылаться, понять это непосредственно из текстового описания непросто, см. следующий код:
fun main(args: Array<String>) {
var child: Child = Child()
var fields: Array<Field> = child.javaClass.declaredFields;
for (field in fields) {// 只有一个值 prop
println(field.name)
}
// 由于 propertyWithImplementation 是非 backing field 的,所以下面的语句不起效果
child.propertyWithImplementation = "sdafasfsda"
println(child.propertyWithImplementation) // foo
child.prop = 30 // 由于 Child 中覆写了该属性,且可为 backing field ,所以可以赋值
println(child.prop) // 30
}
interface MyInterface {
var prop: Int // 抽象属性
var propertyWithImplementation: String // 非抽象属性,且非 backing field
get() = "foo"
set(value) {
// 如果强制声明为 field 则,编译器提示错误,无法编译
// field = value
}
}
class Child : MyInterface {
// 抽象属性必须覆写
override var prop: Int = 29
// 如果这里覆写了 propertyWithImplementation 并是 backing field 的,则上面打印结果就不再是 foo 而是 sdafasfsda ,
// fieds 中也会多一个 propertyWithImplementation
// override var propertyWithImplementation: String = ""
// set(value) {
// field = value
// }
}
переопределить конфликт
Когда класс реализует несколько интерфейсов, в этих интерфейсах может быть несколько реализаций методов с одинаковыми именами. На этом этапе мы можем использовать super<имя класса>.method(), чтобы определить, какой метод родительского класса вызывается, например:
interface A {
fun foo() { print("A") }
fun bar()
}
interface B {
fun foo() { print("B") }
fun bar() { print("bar") }
}
class C : A {
override fun bar() { print("bar") }
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}