Kotlin学习历程——抽象类与接口

Kotlin语言中文站

抽象类

类以及其中的某些成员可以声明为abstract表示是抽象类。

/** 父类 */
open class Machine {
    
    
    open fun name(){
    
    }
}

/** 抽象类 */
abstract class Mobilephone : Machine(){
    
    
    //强制子类实现
    abstract override fun name();
}

注意:抽象类是不可实例化的,必须由子类实现,因此抽象类不需要用open修饰。


接口

Kotlin接口可以即包含抽象方法的声明也包含实现。与抽象类不同的是,接口无法保存状态。它可以有属性但必须声明为抽象或提供访问器实现。

使用关键字interface来定义一个接口:

interface A {
    
    
    //有函数体的函数
    fun foo() {
    
    
        println("A##foo")
    }

    //待实现的函数
    fun bar()
}

实现接口

一个类可以实现一个或者多个接口。

class C : A {
    
    
    
    //实现接口A的方法
    override fun bar() {
    
    
        print("C##bar")
    }
}

接口中的属性

你可以在接口中定义属性。在接口中声明的属性要么是抽象的,要么提供访问器的实现。在接口中声明的属性不能有幕后字段(backing field),因此接口中声明的访问器不能引用它们,否则会提示错误。

interface Named {
    
    
    //抽象属性
    val name: String

    //提供访问器的实现
    val simpleName: String
        get() = ""

    fun foo() {
    
    
        print(name)
    }
}

使用幕后字段报错,如下图:

接口继承

一个接口可以从其他接口派生,从而既提供基类成员的实现也声明新的函数和属性。很自然的,实现这样接口的类只需定义所缺少的实现:

interface Person : Named {
    
    
    val firstName : String
    val lastName : String

    override val name: String
        get() = "$firstName _ $lastName"
    
    fun log() {
    
    
        print(name)
    }
}

//数据类Employee
data class Employee(
        //只实现需要实现的,不必实现name
        override val firstName: String,
        override val lastName: String,
        val pos: Int)
    : Person {
    
    
}

解决覆盖冲突

实现多个接口时,可能会遇到同一方法继承多个实现的问题。

//接口A
interface A {
    
    
    fun foo() {
    
    
        println("A##foo")
    }
    fun bar()
 
    fun a(){
    
    }
}

//接口B
interface B {
    
    
    fun foo() {
    
    
        println("B##foo")
    }

    fun bar() {
    
    
        println("B##bar")
    }
    
    fun b(){
    
    }
}

//接口D
class D : A, B {
    
    
    override fun foo() {
    
    
        //选择实现
        super<A>.foo()
        super<B>.foo()
        
        
        //也可以自己处理逻辑,不调用父类
    }

    override fun bar() {
    
    
        //因为A的bar未实现,所以这里调用super只能调用B,所以没有声明泛型
        super.bar()
        
        
        //也可以自己处理逻辑,不调用父类
    }
}

如上我们从 A 和 B 派生 D,我们需要实现我们从多个接口继承的所有方法,实现的方法具体执行什么代码逻辑可由我们自己决定。

这里我总结一下:

  • 接口中抽象的方法是一定需要实现的,如上面的bar()
  • 如果继承的多个接口拥有相同的方法,如上面foo(),是一定需要实现的。
  • 其他父类的方法如a() 或者 b()可由我们自己决定是否需要实现。

上一篇:Kotlin学习历程——继承
下一篇:Kotlin学习历程——扩展

猜你喜欢

转载自blog.csdn.net/hepingdev/article/details/124079596