文章目录- I . 接口总结
- II . 接口声明
- III . 接口实现
- IV . 接口中的方法
- V . 接口中的属性 ( 变量 / 常量 )
- VI . 接口中的属性属性覆盖 ( 变量 / 常量 )
- VII . 接口覆盖冲突问题
- VIII . 接口继承接口
I . 接口总结
接口总结 :
① 声明与实现 : 使用 interface 关键字声明接口 , 实现时需要重写所有的抽象成员 ( 属性 / 方法 ) ;
② 接口成员 : 接口中的 正常成员属性和成员方法默认使用 open 关键字修饰 , 接口中的抽象成员属性和抽象成员方法默认使用 abstract open 关键字修饰 ;
③ 接口属性及覆盖 : 变量属性声明成抽象属性 , 常量属性可以声明成抽象属性 , 也可以添加访问器 ;
④ 接口覆盖冲突问题 : 实现类实现多个接口 , 使用 super<接口名称> 调用不同接口的正常方法 ;
II . 接口声明
1 . 接口声明 : 接口使用 interface 接口名称
格式定义 ;
① 接口默认 open 修饰 : 接口 , 默认使用 open 关键字修饰 , 可以直接继承 ;
② 接口方法默认 open 修饰 : 接口中的方法 , 默认使用 open 关键字修饰 , 可以直接 override 重写 ; 抽象方法可以省略 abstract 关键字修饰 ;
② 接口属性默认 open 修饰 : 接口中的属性 , 默认使用 open 关键字修饰 , 可以直接 override 重写 ; 抽象属性可以省略 abstract 关键字修饰 ;
代码语言:javascript复制//定义接口
interface Intf{}
III . 接口实现
接口实现 :
① 没有构造函数委托 : 实现接口时不用调用其构造函数 , 因此在子类声明时 , 接口名称后没有括号 ;
② 必须重写抽象方法与抽象属性 : 接口中的没有初始化的属性是抽象属性 , 没有方法体的方法是抽象方法 , 其省略了 abstract 和 open 关键字 ;
代码语言:javascript复制//接口定义
interface Intf{
//抽象属性
var age : Int
//抽象方法
fun action_abstract()
}
//接口实现 , 注意没有构造函数委托
class Impl : Intf {
//重写抽象属性
override var age: Int = 18
//重写抽象方法
override fun action_abstract() {
println("Impl : action_abstract")
}
}
IV . 接口中的方法
1 . 接口中的方法 : 接口中的方法默认使用 open 修饰 , 可以直接在实现类中重写覆盖 ;
① 抽象方法 : 接口中可以定义抽象方法 , 接口中没有方法体的抽象方法可以省略 abstract 关键字 , 所有方法默认使用 open 修饰 ;
② 正常方法 : 也可以定义普通的方法 , 普通方法默认使用 open 修饰 ;
③ 与 Java 对比 : 这一点与 Java 不同 , Java 中接口必须都是抽象方法 ;
代码语言:javascript复制interface Intf{
//接口中的方法默认使用 abstract 修饰
fun action_abstract()
//接口中可以定义正常方法
fun action_real(){
println("action_real")
}
}
2 . 接口中方法重写 : 重写的方法必须使用 override 关键字修饰 ;
代码语言:javascript复制//接口定义
interface Intf{
//接口中的方法默认使用 abstract open 修饰
fun action_abstract()
//接口中可以定义正常方法 , 默认使用 open 修饰
fun action_real(){
println("Intf : action_real")
}
}
//接口实现类
abstract class Impl : Intf {
//实现类中实现接口的抽象方法
override fun action_abstract() {
println("Impl : action_abstract")
}
//实现类中重写接口中的正常方法
override fun action_real() {
super.action_real()
println("Impl : action_real")
}
}
V . 接口中的属性 ( 变量 / 常量 )
1 . 接口属性 : 接口无法实例化 , 无法保存状态 , 接口中的属性不能初始化 , 此时有两种选择 : ① 将该属性定义成抽象的 ( 变量常量都可 ) , ② 提供 get 方法 ( 只有常量才可以 ) ;
① 抽象属性 ( 变量 / 常量 ) : 被 abstract 修饰的 常量 var 或 变量 val 属性 , 没有初始化值 , 没有 getter 和 setter 方法 ;
代码语言:javascript复制interface Intf{
//抽象属性 常量 , 默认被 abstract open 修饰 ( 可省略 )
abstract open val age : Int
//抽象属性 变量 , 默认被 abstract open 修饰 ( 可省略 )
abstract open var name : String
}
② 省略的修饰符 ( 变量 / 常量 ) : 接口中的属性和方法默认自带 open 修饰符 , 接口中的抽象属性 和 抽象方法 可以省略 abstract , 因此这里可以省略 open 和 abstract 关键字 , 加上也不会出错 ;
( 下面的抽象属性与 ① 中的抽象属性是等价的 )
代码语言:javascript复制interface Intf{
//抽象属性 常量 , 默认被 abstract open 修饰 ( 可省略 )
val age : Int
//抽象属性 变量 , 默认被 abstract open 修饰 ( 可省略 )
var name : String
}
③ 提供访问器 ( 常量 ) : 可以给属性提供一个访问器 , 但是明显接口无法实例化 , 该访问器调用不了 ;
( 常量可以提供一个访问器 , 变量只能定义成抽象属性 )
代码语言:javascript复制interface Intf{
//抽象属性 常量 , 常量可以提供一个访问器
val age : Int
get() = 18
//抽象属性 变量 , 变量只能声明成抽象属性 , 不能添加访问器
var name : String
}
VI . 接口中的属性属性覆盖 ( 变量 / 常量 )
接口中的属性覆盖 :
① 抽象属性 : 接口中的 变量 / 常量 属性可以声明成抽象的 ;
② 关于访问器 : 只有常量才能使用添加访问器替代抽象属性方案 , 变量不能添加访问器 ;
③ 常量与变量 : 覆盖属性 , 可以使用变量覆盖常量 , 反过来不行 , 变量只能使用变量覆盖 ;
代码语言:javascript复制//1 . 接口定义
interface Intf{
//抽象属性 常量 , 默认被 abstract open 修饰 ( 可省略 )
//常量可以提供一个访问器 , 变量只能声明成抽象属性 , 不能添加访问器
val age : Int
//抽象属性 变量 , 默认被 abstract open 修饰 ( 可省略 )
//常量可以提供一个访问器 , 变量只能声明成抽象属性 , 不能添加访问器
var name : String
}
//2 . 接口实现类
abstract class Impl : Intf {
//覆盖属性 , 可以使用变量覆盖常量 , 反过来不行
override var age: Int = 18
//覆盖属性 , 变量只能使用变量覆盖
override var name: String = "Tom"
}
VII . 接口覆盖冲突问题
1 . 接口覆盖冲突问题描述 : 一个类可以实现多个接口 , 如果多个接口中出现相同函数签名的函数 ( 正常带方法体的函数 ) , 如何调用不同接口的相同签名函数 ; ( 注意 : 这里调用的方法是有方法体的正常方法 )
2 . 覆盖冲突解决方案 : 可以通过 super<接口名> 调用不同接口的正常方法 ;
3 . 代码示例 : Intf1 和 Intf2 接口中都定义了非抽象函数 action_real , Impl 类实现了两个接口 , 通过使用 super.action_real() 调用 Intf1 中的 action_real 方法 , 通过使用 super.action_real() 调用 Intf2 中的 action_real 方法
代码语言:javascript复制//接口 1 定义
interface Intf1{
fun action_abstract()
fun action_real(){
println("Intf1 : action_real")
}
}
//接口 2 定义
interface Intf2{
fun action_abstract()
fun action_real(){
println("Intf2 : action_real")
}
}
//实现两个接口
class Impl : Intf1 , Intf2 {
override fun action_abstract() {
println("Impl : action_abstract")
}
override fun action_real() {
//调用 Intf1 接口中的 action_real 方法
super<Intf1>.action_real()
//调用 Intf2 接口中的 action_real 方法
super<Intf2>.action_real()
}
}
VIII . 接口继承接口
接口继承接口 :
① 派生接口继承 : 一个接口可以继承另一个接口 , 派生接口拥有基类接口的成员 ;
② 派生接口新成员 : 派生接口声明新的接口成员和属性 ;
③ 子类实现派生接口 : 需要实现两个接口的所有的抽象成员 ( 属性 / 方法 ) ;
代码语言:javascript复制//接口定义
interface Intf1{
//抽象属性
var age : Int
//抽象方法
fun action_abstract()
}
//接口定义
interface Intf2 : Intf1{
//抽象属性
var name : String
//抽象方法
fun action_abstract2()
}
//接口实现 , 注意没有构造函数委托
//需要实现 Intf1 和 Intf2 中的抽象成员
class Impl : Intf2 {
override var name: String = "Tom"
override var age: Int = 18
override fun action_abstract() {
println("Impl : action_abstract")
}
override fun action_abstract2() {
println("Impl : action_abstract")
}
}