Kotlin от Learning to Android Глава 8 Интерфейс

интерфейс

Интерфейсы в 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()
    }
}

Guess you like

Origin blog.csdn.net/niuzhucedenglu/article/details/72904347