ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 接口 Kotlin 中的接口与 Java 8 非常类似。它们可以包含一些抽象方法声明,与方法实现一样。令它们与抽象类不同的地方是接口不能存储状态。它们可以有属性但这需要被抽象或是提供访问器的实现。 接口使用关键字 `interface` 定义 ``` kotlin interface MyInterface { fun bar() fun foo() { // optional body } } ``` ## 实现接口 类或对象能实现一个或多个接口 ``` kotlin class Child : MyInterface { override fun bar() { // body } } ``` ## 接口中的属性 你可以在接口中声明属性。在接口中声明的属性要么是抽象的,要么它能提供访问器的实现。接口中声明的属性不能有后台字段,因此接口中声明的访问器不能引用它们。 ``` kotlin interface MyInterface { val property: Int // abstract val propertyWithImplementation: String get() = "foo" fun foo() { print(property) } } class Child : MyInterface { override val property: Int = 29 } ``` ## 解决覆盖冲突 当我们在我们的超类列表中声明了一些类型,可能会出现我们继承了多个相同方法的实现。例如 ``` kotlin 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() } } ``` 接口 *A* 和 *B* 都声明了函数 *foo()* 和 *bar()*。它们都实现 *foo()*,但仅仅 *B* 实现了 *bar()*(*bar() 在 *A* 中没有被标记为抽象,因为如果这个函数没有函数体,接口会默认如此)。现在,如果我们从 *A* 衍生出具体类 *C*,很明显我们必须覆盖 *bar()* 并提供一个实现。而且如果 我们从 *A* 和 *B* 衍生了 *D*,我们不用覆盖 *bar()*,因为我们有继承的它的唯一的实现。但我们已经继承了两个 *foo()* 的实现,因此编译器无法知道该选择哪个,然后会强制我们去覆盖 *foo()* 并说明什么才是我们真正想要的。