Kotlin类的进阶——继承&抽象&重写&重载&接口&扩展

一、继承

  1. 表示符号
  2. 父类需要用open修饰,默认是用final修饰,不可继承
  3. 如果需要重写父类的方法和属性,父类的方法和属性也必须使用open修饰;
  4. 重写关键字override
  5. 重写属性。子类重写父类属性,只能扩充外部功能,不能减少外部功能。如果父类属性存在gettersetter方法,子类覆盖他的属性也必须有gettersetter方法。即父类属性用var修饰,子类覆盖他的属性不得用val修饰
    5.重写属性可以在构造函数中进行

二、抽象&重写&重载

  1. 关键字: abstract
  2. 重载:在同一个类中,方法名相同,参数类型、参数个数、排列顺序不同
  3. 重写:在两个有继承关系的类之间,方法名相同,参数类型、个数、排列顺序都相同

三、接口

  1. 关键字:interface
  2. 注意:接口没有默认构造方法,所以实现接口的时候不需要在接口名称后面加括号
  3. Java中,接口中的方法必须是抽象的,没有方法体;但是在Kotlin中,允许存在实现了的方法
  4. 接口中属性如果是变量则不可以初始化,但是可以有gettersetter方法,但是在gettersetter方法中不可以出现field字段
  5. 接口中的属性的gettersetter方法必须重写
  6. 如果两个接口都声明了一个相同的方法,一个是抽象的,一个是实例化的,子类是实现的时候,必须实现该方法,可以重写,也可以通过super调用已经实例化的方法
  7. 如果两个接口都声明了一个相同的方法,并且另个方法都是实例化的,子类是实现的时候,必须实现该方法,可以重写,也可以通过super<接口名>调用已经实例化的方法,可以同时调用两个父类的实例化方法

四、修饰符

可见性修饰符
- private 同类
- protected 同类或者子类
- internal 同moudle
- public 不同moudle

五、类的扩展

  1. 扩展函数
    • 形式 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
  • 扩展函数支持重载,但是不支持重写。如果扩展函数的函数名和参数与类的函数名和参数相同,则执行类本身的函数
  • 可以对空类型进行函数扩展

    1. 扩展属性
  • 形式
  var/val 类名.属性名
   get() = 
   set(value){

}
var ConvertInterface.money: Double
    get() = 1000.00;
    set(value) {

    }
  • 扩展的属性不是在原类中增加相关属性
  • 扩展属性没有“backing field”
  • 扩展属性不支持默认初始化;需要明确定义“ getters/setters
  • 由于各种限制,扩展属性不常用
  • 不能再main中扩展属性

    1. 扩展属性和函数的使用范围
  • 一般都是在顶层(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,可以使用[email protected]
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()
    }

猜你喜欢

转载自blog.csdn.net/qq_26585943/article/details/80303825