Kotlin------類和對象(一)

類聲明
和Java一樣,Kotlin中使用關(guān)鍵字class來聲明一個類。如下即是聲明一個最簡單的沒有任何屬性和方法的類

// 沒有任何屬性、方法的Invoice 類
class Invoice {}

一個完整的類聲明包含類名,類頭(指定構(gòu)造參數(shù)、構(gòu)造方法等),類體(用大括號包裹的部分)。類頭和類體這兩個部分并非必要的,類頭和類體都是可選的; 如果一個類沒有類體,可以省略花括號。

class Invoice

構(gòu)造函數(shù)
在 Kotlin 中的一個類可以有一個主構(gòu)造函數(shù)和一個或多個次構(gòu)造函數(shù)。主構(gòu)造函數(shù)是類頭的一部分:它跟在類名(和可選的類型參數(shù))后。

class Person constructor(firstName: String) {
}

如果主構(gòu)造函數(shù)沒有任何注解或者可見性修飾符,可以省略這個 constructor 關(guān)鍵字。

class Person(firstName: String) {
}

主構(gòu)造函數(shù)不能包含任何的代碼。初始化的代碼可以放到以 init 關(guān)鍵字作為前綴的初始化塊(initializer blocks)中:

class Customer(p : Int) {
    init {
        println("Customer類初始化")
    }
}

次構(gòu)造函數(shù)
二級構(gòu)造函數(shù),也稱為次級構(gòu)造函數(shù)。關(guān)于二級構(gòu)造函數(shù),主要有以下幾點:

次級構(gòu)造函數(shù)不能省略constructor關(guān)鍵字;
當(dāng)類擁有主構(gòu)造函數(shù)時,任何一個二級構(gòu)造函數(shù)都需要直接或間接通過另一個二級構(gòu)造函數(shù)代理主構(gòu)造函數(shù);
類中的一個構(gòu)造函數(shù)代理另一個構(gòu)造函數(shù),需要使用關(guān)鍵字this;
類也可以聲明前綴有 constructor的次構(gòu)造函數(shù):

class Person {
    constructor(parent: Person) {
        parent.children.add(this )
    }
}
class Person constructor(id: Int) {//(構(gòu)造函數(shù)No.0)主構(gòu)造函數(shù)
    var id = id//主構(gòu)造函數(shù)初始化id
    var name = ""
    var age = 0
    //(構(gòu)造函數(shù)No.1)直接代理主構(gòu)造函數(shù)
    constructor(name: String, id: Int) : this(id) {
        this.name = name
    }
    //(構(gòu)造函數(shù)No.2)代理了構(gòu)造函數(shù)No.1,間接代理主構(gòu)造函數(shù)
    constructor(name: String, age: Int, id: Int) : this(name, id) {
        this.age = age
    }
}

繼承
和所有的Java類都有一個共同的父類Object一樣且不支持同時繼承多個父類。Kotlin中所有的類都擁有一個共同的父類Any(但Any不是Object,不要搞錯)。Any相比Object其內(nèi)部結(jié)構(gòu)要簡單很多,僅有equals()、hashCode()、toString()三個抽象方法。

//默認(rèn)情況下,在 Kotlin 中所有的類都是 final,
//抽象是面向?qū)ο缶幊痰奶卣髦唬惐旧恚蝾愔械牟糠殖蓡T,都可以聲明為abstract的。抽象成員在類中不存在具體的實現(xiàn)。

open class Base(p: Int){
    init {
        println("基類")
    }

    //重寫
    //在基類中,使用fun聲明函數(shù)時,此函數(shù)默認(rèn)為final修飾,不能被子類重寫。
    // 如果允許子類重寫該函數(shù),那么就要手動添加 open 修飾它, 子類重寫方法使用 override 關(guān)鍵詞:
    open fun sdutent() {
        println("基類方法")
    }
}
class Customer(p : Int): Base(p) {

    init {
        println("Customer類")
    }

    constructor(p: Int,n: String):this(p){
        println("$p is n= $n")
    }

    override fun sdutent() {
        super.sdutent()
        println("重寫基類的方法")
    }
}

屬性和賦值
在聲明一個最簡單的空殼類之后,我們來為它增加一些類屬性。Kotlin中類的屬性可以用var或者val關(guān)鍵字進行聲明,其中var為可變屬性,val為只讀屬性(相當(dāng)于Java的final)。

class Student {
    var name = "名字" //名字屬性可變,用var
    val birthday = "1994-10-26" //生日屬性不可變,用val
}

像上面這樣就簡單的為Student類聲明了name和birthday兩個屬性,且在聲明屬性時進行了初始化,按照Kotlin的類型推斷特點,name和birthday就是屬于String類型(不知道類型推斷的同學(xué)可以翻閱前面的寫的文章)。現(xiàn)在我想為Student類添加一個age屬性,但是我并不想在聲明時進行初始化,用Java寫起來非常簡單即可實現(xiàn)

public class JavaStudent {
    private String name = "名字";
    private String birthday = "1994-10-26";
    private int age;//Java版的實現(xiàn)
}

按照J(rèn)ava的實現(xiàn)套路直接套入Kotlin你會發(fā)現(xiàn)IDE直接報錯并提示property must be initialized or be abstract

image

按照提示我們必須把類和字段都聲明為abstract才可以通過編譯。

abstract class Student {
    var name = "名字" //名字屬性可變,用var
    val birthday = "1994-10-26" //生日屬性不可變,用val
    abstract var age: Int
}

這樣未免太過麻煩,而且理解起來也非常奇怪。Kotlin提供了延遲初始化的方式來解決初始化的問題,使用關(guān)鍵字lateinit即可,這樣就無需聲明abstract了。

image

可惜使用lateinit延遲初始化age之后,IDE依舊報錯,這次提示的內(nèi)容是lateinit modifier is not allowed on primitive type properties。Kotlin并不支持對原生類型進行l(wèi)ateinit,為什么呢?因為Kotlin會使用null來對每一個用lateinit修飾的屬性做初始化,而基礎(chǔ)類型是沒有null類型,所以無法使用lateinit。這點很好理解,就像可以把int型變量賦值為0,卻無法賦值為null一樣。所以這里為了通過IDE的編譯,我們可以采用兩種方案,要么還是直接在age聲明時進行初始化,要么不用基礎(chǔ)類型來定義age。

class Student {
    var name = "名字" //名字屬性可變,用var
    val birthday = "1994-10-26" //生日屬性不可變,用val
    var age = 0 //直接使用0初始化age,age為Int型
    lateinit var ageStr: String //String不是基礎(chǔ)類型,可以使用lateinit初始化
}

創(chuàng)建對象
調(diào)用類的構(gòu)造器,調(diào)用方式和使用普通函數(shù)一樣:

val person = Student ()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 面向?qū)ο缶幊蹋∣OP) 在前面的章節(jié)中,我們學(xué)習(xí)了Kotlin的語言基礎(chǔ)知識、類型系統(tǒng)、集合類以及泛型相關(guān)的知識。...
    Tenderness4閱讀 4,479評論 1 6
  • 本文是在學(xué)習(xí)和使用kotlin時的一些總結(jié)與體會,一些代碼示例來自于網(wǎng)絡(luò)或Kotlin官方文檔,持續(xù)更新... 對...
    竹塵居士閱讀 3,331評論 0 8
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,841評論 2 9
  • 如果描述的類型不是基本類型怎么辦? 任何復(fù)雜的數(shù)據(jù)類型都是由基本的數(shù)據(jù)類型構(gòu)成的 面向?qū)ο?使用基本數(shù)據(jù)類型描述復(fù)...
    JunChow520閱讀 2,220評論 0 1
  • 寫在開頭:本人打算開始寫一個Kotlin系列的教程,一是使自己記憶和理解的更加深刻,二是可以分享給同樣想學(xué)習(xí)Kot...
    胡奚冰閱讀 1,432評論 5 11