Android:Kotlin詳細入門學習指南-類和對象-基礎語法(四)

本人也是在初學Kotlin,如有錯誤,請幫忙指出,持續更新

Android:Kotlin詳細入門學習指南-類和對象-基礎語法(四)

建議先看看前面的文章
Android:Kotlin詳細入門學習指南-基礎語法(一)

Android:Kotlin詳細入門學習指南-基本類型-基礎語法(二)

Android:Kotlin詳細入門學習指南-包-控制流-返回與跳轉-基礎語法(三)

這篇文章分享的內容比較多,建議先關注收藏,再查看,以免迷路

類和對象

  • 類和繼承
  • 屬性和字段
  • 接口
  • 可見性修飾詞
  • 擴展
  • 數據對象
  • 泛型
  • 嵌套類
  • 枚舉類
  • 對象表達式和聲明
  • 委派模式
  • 委派屬性
類和繼承

在 Kotlin 中類用 class 聲明:

class Invoice { }

類的聲明包含類名,類頭(指定類型參數,主構造函數等等),以及類主體,用大括 號包裹。類頭和類體是可選的;如果沒有類體可以省略大括號。

構造函數

Kotlin的構造函數和java的還是有點區別
在 Kotlin 中類可以有一個主構造函數以及多個二級構造函數。主構造函數是類頭的 一部分:跟在類名後面(可以有可選的類型參數)。

class Person constructor(firstName: String) { }

如果主構造函數沒有註解或可見性說明,則 constructor 關鍵字是可以省略:

class Person(firstName: String){ }

主構造函數不能包含任意代碼。初始化代碼可以放在以 init 做前綴的初始化塊內

class Customer(name: String) { 
    init {
        logger,info("Customer initialized with value ${name}") 
    } 
}

注意主構造函數的參數可以用在初始化塊內,也可以用在類的屬性初始化聲明處:

class Customer(name: String) { 
    val customerKry = name.toUpperCase() 
}

聲明屬性並在主構造函數中初始化,在 Kotlin 中有更簡單的語法

class Person(val firstName: String, val lastName: String, var age : Int) { }

在主構造函數中的屬性可以是可變的( var )或只讀的( val )。 如果構造函數有註解或可見性聲明,則 constructor 關鍵字是不可少的

二級構造函數

類似java的重載
類也可以有二級構造函數,需要加前綴 constructor :

class Person { 
    constructor(parent: Person) { 
        parent.children.add(this) 
    } 
}

如果類有主構造函數,每個二級構造函數都要,或直接或間接通過另一個二級構造 函數代理主構造函數。在同一個類中代理另一個構造函數使用 this 關鍵字:

class Person(val name: String) { 
    constructor (name: String, paret: Person) : this(name) { 
        parent.children.add(this) 
    } 
}

如果一個非抽象類沒有聲明構造函數(主構造函數或二級構造函數),它會產生一個 沒有參數的構造函數。該構造函數的可見性是 public 。如果你不想你的類有公共的 構造函數,你就得聲明一個擁有非默認可見性的空主構造函數:

class DontCreateMe private constructor () { }

注意:在 JVM 虛擬機中,如果主構造函數的所有參數都有默認值,編譯器會 生成一個附加的無參的構造函數,這個構造函數會直接使用默認值。這使得 Kotlin 可以更簡單的使用像 Jackson 或者 JPA 這樣使用無參構造函數來創建類 實例的庫。

創建類的實例
val invoice = Invoice() 
val customer = Customer("Joe Smith")

注意 Kotlin 沒有 new 關鍵字。
內部類要使用inner關鍵字。

類成員

類可以包含:

  • 構造函數和初始化代碼塊
  • 函數
  • 屬性
  • 內部類
  • 對象聲明
繼承

Kotlin 中所有的類都有共同的父類 Any ,java是Obejct,它是一個沒有父類聲明的類的默認父 類:
Any 不是 java.lang.Object ;事實上它除了 equals() , hashCode() 以 及 toString() 外沒有任何成員了。
聲明一個明確的父類,需要在類頭後加冒號再加父類

open class Base(p: Int) 
class Derived(p: Int) : Base(p)

普通的類如果需要被繼承就需要有open關鍵字
open 註解與java中的 final 相反:它允許別的類繼承這個類。默認情形下,kotlin 中所有的類都是 final

複寫方法
open class Base { 
    open fun v() {} 
    fun nv() {} }
class Derived() : Base() { 
    override fun v() {} 
}

對於 Derived.v() 來說 override 註解是必須的。如果沒有加的話,編譯器會 提示。如果沒有 open 註解,像 Base.nv() ,在子類中聲明一個同樣的函數是不 合法的,要麼加 override 要麼不要複寫。在 final 類(就是沒有open註解的類) 中, open 類型的成員是不允許的。
普通方法標記open,可被重寫

複寫屬性

複寫屬性與複寫方法類似,在一個父類上聲明的屬性在子類上被重新聲明,必須添 加 override ,並且它們必須具有兼容的類型。每個被聲明的屬性都可以被一個帶 有初始化器的屬性或帶有getter方法的屬性覆蓋

複寫規則

在 kotlin 中,實現繼承通常遵循如下規則:如果一個類從它的直接父類繼承了同一 個成員的多個實現,那麼它必須複寫這個成員並且提供自己的實現(或許只是直接用 了繼承來的實現)。爲表示使用父類中提供的方法我們用 super<Base> 表示:

open class A { 
    open fun f () { 
        print("A") 
    } 
    fun a() { 
        print("a") 
    } 
}
interface B { 
    fun f() { 
        print("B") 
} // 接口的成員變量默認是 open 的 
fun b() { 
    print("b") 
    } 
}
class C() : A() , B { 
// 編譯器會要求複寫f() 
    override fun f() { 
        super<A>.f() // 調用 A.f() 
        super<B>.f() // 調用 B.f() 
    } 
}

可以同時從 A 和 B 中繼承方法,而且 C 繼承 a() 或 b() 的實現沒有任何問題,因爲 它們都只有一個實現。但是 f() 有倆個實現,因此我們在 C 中必須複寫 f() 並且提供 自己的實現來消除歧義。
這次就先分享到這裏,下次再繼續分享。

本人也是在初學Kotlin,如有錯誤,請幫忙指出,持續更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章