一、继承
- 表示符号
:
- 父类需要用
open
修饰,默认是用final
修饰,不可继承 - 如果需要重写父类的方法和属性,父类的方法和属性也必须使用
open
修饰; - 重写关键字
override
- 重写属性。子类重写父类属性,只能扩充外部功能,不能减少外部功能。如果父类属性存在
getter
和setter
方法,子类覆盖他的属性也必须有getter
和setter
方法。即父类属性用var
修饰,子类覆盖他的属性不得用val
修饰
5.重写属性可以在构造函数中进行
二、抽象&重写&重载
- 关键字:
abstract
- 重载:在同一个类中,方法名相同,参数类型、参数个数、排列顺序不同
- 重写:在两个有继承关系的类之间,方法名相同,参数类型、个数、排列顺序都相同
三、接口
- 关键字:
interface
- 注意:接口没有默认构造方法,所以实现接口的时候不需要在接口名称后面加括号
- Java中,接口中的方法必须是抽象的,没有方法体;但是在Kotlin中,允许存在实现了的方法
- 接口中属性如果是变量则不可以初始化,但是可以有
getter
和setter
方法,但是在getter
和setter
方法中不可以出现field
字段 - 接口中的属性的
getter
和setter
方法必须重写 - 如果两个接口都声明了一个相同的方法,一个是抽象的,一个是实例化的,子类是实现的时候,必须实现该方法,可以重写,也可以通过super调用已经实例化的方法
- 如果两个接口都声明了一个相同的方法,并且另个方法都是实例化的,子类是实现的时候,必须实现该方法,可以重写,也可以通过
super<接口名>
调用已经实例化的方法,可以同时调用两个父类的实例化方法
四、修饰符
可见性修饰符
- private 同类
- protected 同类或者子类
- internal 同moudle
- public 不同moudle
五、类的扩展
- 扩展函数
- 形式
fun 类名.方法名() = 方法体
- 形式
fun ConvertInterface.sayBey() = println("Bye")
- 扩展函数是静态解析的,而类的内部函数是动态解析的。即函数调用是根据声明的类型来决定的
var convertInterface: KotlinInterface = ConvertInterface()
var convertInterface1: ConvertInterface = ConvertInterface()
fun ConvertInterface.sayBey() = println("Bye")
fun KotlinInterface.sayBey() = println("Korlin Bye")
convertInterface.sayBey()
convertInterface1.sayBey()
打印值:
Korlin Bye
Bye
- 扩展函数支持重载,但是不支持重写。如果扩展函数的函数名和参数与类的函数名和参数相同,则执行类本身的函数
可以对空类型进行函数扩展
- 扩展属性
- 形式
var/val 类名.属性名
get() =
set(value){
}
var ConvertInterface.money: Double
get() = 1000.00;
set(value) {
}
- 扩展的属性不是在原类中增加相关属性
- 扩展属性没有“backing field”
- 扩展属性不支持默认初始化;需要明确定义“
getters/setters
” - 由于各种限制,扩展属性不常用
不能再
main
中扩展属性- 扩展属性和函数的使用范围
- 一般都是在顶层(top level)定义扩展,在
package `object`
fun JavaInterface.sayHi() = println("Say Hi")
- 在一个类A中扩展另一个类B的函数
(1)与顶层声明相同
(2)如果A,B有同一个方法F1,A中扩展B的函数F2,F2中执行F1,执行的是B中F1。如果想执行A中F1,可以使用this@A.F1
class A {
fun F1(){
println("I am A 中的F1")
}
}
class B {
fun F1(){
println("I am B 中的F1")
}
fun A.F2(){
F1()
println("I am A的拓展函数F2")
}
fun C(a:A){
F1()
a.F2()
}
}
fun main(args: Array<String>) {
var a: A = A()
var b: B = B()
b.C(a)
}
打印
I am B 中的F1
I am A 中的F1
I am A的拓展函数F2
把其中的类B修改一下
class B {
fun F1(){
println("I am B 中的F1")
}
fun A.F2(){
this@B.F1()
println("I am A的拓展函数F2")
}
fun C(a:A){
F1()
a.F2()
}
}
打印
I am B 中的F1
I am B 中的F1
I am A的拓展函数F2
(3)一个类中对于其他继承的类的拓展函数也是静态解析的
open class C {
}
class A : C() {
fun F1() {
println("I am A 中的F1")
}
}
package `object`
class B {
fun F1(){
println("I am B 中的F1")
}
fun A.F2(){
this@B.F1()
println("I am A的拓展函数F2")
}
fun C.F2(){
this@B.F1()
println("I am C的拓展函数F2")
}
fun C(a:C){
F1()
a.F2()
}
}
fun main(args: Array<String>) {
var a: A = A()
var c: C = C()
var b: B = B()
b.C(a)
b.C(c)
}
执行结果
I am B 中的F1
I am B 中的F1
I am C的拓展函数F2
I am B 中的F1
I am B 中的F1
I am C的拓展函数F2
都是执行C中的拓展函数F2,因为我们b.c传入的是C
fun C(a:C){
F1()
a.F2()
}