Kotlin高階面向對象

高級部分

抽象類主要作爲多個類的模板,而接口則定義了多個類應該遵守的規範

拓展

Kotlin的拓展是一個很獨特的功能(Java中是不存在的)

基類拓展的方法,子類對象也是可以使用的。 拓展方法的this和成員方法的this一樣是該對象的引用。

import java.util.*;
fun String.say() {
    println("Hello MCM!");
}
fun main(args: Array<String>) {
    var a : String = "Hello World!";
    a.say();
}

還可以在fun後添加 <T> 聲明該函數是泛型函數

fun <T> ArrayList<T>.say() {
    for (i in this.indices) {
        println(this[i]);
        println("Hello World");
    }
}
fun main(args: Array<String>) {
    var list: ArrayList<String> = ArrayList<String>();
    list.add("A");
    list.add("B");
    list.add("C");
    list.say();
}

拓展的實現機制

Java是靜態語言,一個類被定義完成無法動態添加和刪除成員,除非重新編譯該類

成員方法執行動態解析(由運行時類型決定)

拓展方法執行靜態解析(由編譯時類型決定)

open class BASE {
    open fun dynamic(){
        println("BASE_DY");
    }
}
class EXTEND : BASE(){
    override fun dynamic() {
        println("EXTEND_DY");
    }
}
fun BASE.static() {
    println("BASE_ST");
}
fun EXTEND.static() {
    println("EXTEND_ST");
}
fun main(args: Array<String>) {
    var base: BASE = EXTEND();
    base.dynamic();
    base.static();
}

拓展屬性

拓展屬性都是不能擁有幕後字段的,可以爲其提供自定義的幕後字段(private),或者使用計算字段

var <T> ArrayList<T>.last_index
    get() = this.size - 1
    set(value) {}
fun main(args: Array<String>) {
    var arr: ArrayList<String> = ArrayList<String>()
    arr.add("Hello");
    arr.add("World");
    arr.add("!");
    println(arr.last_index); //Output: 2
}

以成員方式定義拓展

拓展的作用域只侷限於這個類中,在類外時訪問不到拓展的任何內容。

import java.util.*;
import kotlin.collections.ArrayList

class A 
class B {
    var a = A();
    fun A.say() {
        println("Hello World");
    }
    fun test() {
        a.say();
    }
}
fun main(args: Array<String>) {
    var b = B();
    b.test();
    // b.a.say();會報錯,因爲拓展的作用域只在B類中 
}

若在拓展的函數中使用的方法在 本類和被拓展的類中重名,參數列表也一樣 返回值也一樣的情況下,會優先使用被拓展類中的那個方法,除非使用 this@當前類名.方法 這種形式才能使用本類的方法。

之所以使用這種方式是因爲默認的this是被拓展類對象的引用,通過 this@當前類名 這種方式可以臨時將this作爲當前類對象引用

class A {
    fun hello() {
        println("Hello A!");
    }
}
class B {
    fun hello() {
        println("Hello B!");
    }

    var a = A();
    fun A.say() {
        hello();
        this@B.hello();
    }
    fun test() {
        a.say();
    }
}
fun main(args: Array<String>) {
    var b = B();
    b.test();
}

帶接收者的匿名函數

使用匿名函數爲類拓展,該拓展函數所屬的類也是該函數的接收者。

這種匿名函數也稱作 “帶接收者的匿名函數”

只要省略拓展函數的名即可

open class A
class B : A()
fun main(args: Array<String>) {
    var b = B();
    var hello = fun A.() {
        println("Hello");
    }
    b.hello();

    var say : A.() -> Unit;
    say = {println("Say")}
    b.say();
}

也可以使用Lambda表達式來拓展屬性,這種函數類型爲 拓展類名.函數類型

抽象

包含抽象成員的類只能被定義成抽象類,抽象類種可以沒有抽象成員

抽象類不能被實例化,即使這個抽象類中沒有抽象成員

與Java類似,Kotlin也允許抽象成員重寫非抽象成員

open class BASE {
    open fun say(){
        println("Hello World");
    }
}
abstract class SUB: BASE(){
    override abstract fun say();
}

接口

  1. 修飾符可以是public | internal | private
  2. 一個接口可以有多個直接父接口,但接口只能繼承接口,不能繼承類

接口可以包含抽象方法也可包含非抽象方法,但接口中的屬性沒有幕後字段。

接口的屬性要麼聲明爲抽象屬性,要麼提供setter、getter方法

Kotlin接口成員可支持private和public兩種訪問權限

  1. 對於抽象方法、抽象屬性必須使用public修飾,不加也默認public
  2. 對於不需要被實現類重寫的成員,可以加private修飾,將這些成員在接口內訪問。

接口的繼承

接口完全支持多繼承

雖然不能實例化,但可用來聲明變量。必須引用到具體的實現類。

嵌套類與內部類

嵌套類(默認)

​ 嵌套類相當於靜態內部類,由於Kotlin取消了static修飾符,因此都是非靜態成員。因此嵌套類不可訪問外部類的其他任何成員(只能訪問其他嵌套類)

class PERSON {
    var x = 1;
    class HEAD {
        fun say() {
            println(x); //嵌套類(靜態內部類),訪問不到x
        }
    }
}
fun main(args: Array<String>) {
    var PH = PERSON.HEAD();
    PH.say();
}

嵌套類相當於外部類的靜態成員,因此外部類的所有方法、屬性、 初始化塊都可以使用嵌套類來定義變量、創建對象。

子類無法使用父類的內部類

open class PERSON_STATIC {
    class HEAD {
        fun say() {
            println("STATIC CLASS");
        }
    }
}

class SUB: PERSON_STATIC()
fun main(args: Array<String>) {
    SUB.HEAD().say();
}

內部類

​ 內部類相當於非靜態成員,內部可以訪問到外部類的所有成員。但是要是想定義一個內部類成員,則必須要實例化一個外部類成員

class PERSON_STATIC {
    class HEAD {
        fun say() {
            println("STATIC CLASS");
        }
    }

}

class PERSON_INNER {
    inner class HEAD {
        fun say() {
            println("INNER CLASS");
        }
    }

}
fun main(args: Array<String>) {
    PERSON_STATIC.HEAD().say();
    PERSON_INNER().HEAD().say(); //必須實例化外部類之後才能實例化內部類
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章