Kotlin接口
1.概述
Kotlin接口即可以有抽象方法,也可以有实现了的方法。接口与抽象类的区别在于接口不能存在状态。接口还可以有属性,不过这些属性只能是抽象的,或者提供访问器的实现。Kotlin的接口与Java的类似,也是可以多继承的。
接下来我们来看年Kotlin如何定义接口,以及多继承情况下如何解决冲突和Kotlin中的属性有何特别。
2.定义
Kotlin接口与Java接口定义一样也是用interface
关键字定义。接口中的方法可以是抽象或已实现了的,如:
interface MyInterface{
fun bar()
fun foo(){
// optional body
}
}
- 1
- 2
- 3
- 4
- 5
- 6
2.接口实现
类或对象都可以实现一个或多个接口。对象我们以后再讨论。现在来看类是如何实现接口的,类只需要实现抽象的方法即可:
class Child: MyInterface{
override fun bar(){
// body
}
}
- 1
- 2
- 3
- 4
- 5
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
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
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() }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
接口A、B实现了foo()
方法,因此D实例调用这个方法时,一定会引发冲突,所以Kotlin要求子类必须重新实现这个方法。当D实例再调用时就是调自己的,就不会引发歧义了。如果要调用接口中那些实现了的方法,如果使用关键字super
加限定词(就是接口名)。如果所示。
如果两个接口有同名的方法,如上例中的bar()
,一个实现了,另一个没有实现的情况,就不会造成冲突,如果要调用那个在接口中已实现的方法,直接用super就可以,不需要加限定词,加了还会提示你说多余呢。为什么不用呢?因为只有一个接口实现了,引用不会存在歧义。
5.属性的使用问题
接口中的属性不能有初始化器,说白了就是不能初始化,如下面就是报错的:
interface A { var age: Int = 44 // 错误!错误!错误!属性的初始化器不能出现在接口中 }
- 1
- 2
- 3
顺便说一句,初始化器就是等号右边的表达式。接口中的属性可以有访问器,即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) {}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
实现接口的属性有两个方法,一是直接赋值,即用初始器,二定义访问器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 }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/107623810
- 点赞
- 收藏
- 关注作者
评论(0)