1.概述
Kotlin接口即可以有抽象方法,也可以有实现了的方法。接口与抽象类的区别在于接口不能存在状态。接口还可以有属性,不过这些属性只能是抽象的,或者提供访问器的实现。Kotlin的接口与Java的类似,也是可以多继承的。
接下来我们来看年Kotlin如何定义接口,以及多继承情况下如何解决冲突和Kotlin中的属性有何特别。
2.定义
Kotlin接口与Java接口定义一样也是用interface 关键字定义。接口中的方法可以是抽象或已实现了的,如:
interface MyInterface{
fun bar()
fun foo(){
// optional body
}
}
2.接口实现
类或对象都可以实现一个或多个接口。对象我们以后再讨论。现在来看类是如何实现接口的,类只需要实现抽象的方法即可:
class Child: MyInterface{
override fun bar(){
// body
}
}
3.接口中的属性
你可以在接口中定义属性。接口中声明的属性可以是抽象的,或者它提供访问器的实现。在接口在声明的属性不能有返回字段(backing field),因此在接口中声明的访问器不能引用它们。
interface MyInterface{
val prop:Int // 抽象的
val propertyWithImplementation: String
get() = "foo" // 提供访问器实现
fun foo(){
print(prop)
}
}
class Child: MyInterface{
override val prop:Int = 29
}
4.多继承产生的冲突
类是可以继承多个接口的,但是这些接口都有相同方法的实现,那么就会造成引用冲突,可以使用super<接口名>.的方式,明确调用哪个接口里实现的方法,这样就不会产生歧义。
interface A {
fun foo(){// 已实现的
Log.i("Man","A")
}
fun bar() // 抽象的
}
package com.example.demo
import android.util.Log
interface B {
fun foo(){// 已实现的
Log.i("Man","B")
}
fun bar(){// 已实现的
Log.i("Man","Bar")
}
}
// D继承了接口A、B
class D:A,B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super.bar()
}
}
接口A、B实现了foo()方法,因此D实例调用这个方法时,一定会引发冲突,所以Kotlin要求子类必须重新实现这个方法。当D实例再调用时就是调自己的,就不会引发歧义了。如果要调用接口中那些实现了的方法,如果使用关键字super加限定词(就是接口名)。如果所示。
如果两个接口有同名的方法,如上例中的bar(),一个实现了,另一个没有实现的情况,就不会造成冲突,如果要调用那个在接口中已实现的方法,直接用super就可以,不需要加限定词,加了还会提示你说多余呢。为什么不用呢?因为只有一个接口实现了,引用不会存在歧义。
5.属性的使用问题
接口中的属性不能有初始化器,说白了就是不能初始化,如下面就是报错的:
interface A {
var age: Int = 44 // 错误!错误!错误!属性的初始化器不能出现在接口中
}
顺便说一句,初始化器就是等号右边的表达式。接口中的属性可以有访问器,即getter,setter,但是它们不能使用返回字段field:
interface A {
var age: Int
set(value){
field = 9999 // 错误!错误!错误! field这个字段在接口中是不可用的
}
var count: Int
get() = 999 // 错误!错误!错误! field这个字段在接口中是不可用的,正常情况,get会有field字段返回的
// 以下这个是OK的,子类都无须再实现这个属性,同时这个属性也不能再赋新值,因为field字段在此处不能用,goods永远是666
var goods: Int
get() = 666
set(value) {}
}
实现接口的属性有两个方法,一是直接赋值,即用初始器,二定义访问器setter和getter:
interface A {
var age: Int
}
class D:A {
override var age: Int
get() = 5
set(value) {} // 没有返回字段field,因此不用初始化器
}
或者
class D:A {
// 使用默认的setter/getter
override var age: Int = 8
}
// 如果setter方法有返回字段field,那么必须用初始化器
class D:A {
override var age: Int = 8
set(value){
field = value+1
}
}
本文深入探讨Kotlin中的接口概念,包括定义、实现、属性、多继承冲突解决及属性使用问题。详细介绍了Kotlin接口与Java接口的相似之处,以及如何在类中实现接口中的抽象方法和已实现的方法。
1794

被折叠的 条评论
为什么被折叠?



