1. 程式人生 > >Kotlin筆記(四)——類和類的構造器

Kotlin筆記(四)——類和類的構造器

從這篇文章開始,我們進入Kotlin面向物件程式設計的世界,這部分的內容相對較多,也是十分重要的,我儘可能將我所學到的介紹給大家。

可見性修飾符

在開始介紹類之前,先來簡單說明一下Kotlin的可見性修飾符。Kotlin的可見性修飾符有四種:public,protected,private和internal,如果不加任何修飾符,預設是public。它們可以用於修飾頂級元素(函式和類等全域性元素),也可以用於修飾類中的成員變數和方法,而後者使用更為廣泛。

當用於修飾類中的成員時,有以下規則:

private:僅在類內可見;

protected:類內和子類中可見;

internal:模組內可見,一個模組是一個Kotlin編譯檔案的集合,而不是一個包

public:隨處可見

類的定義

瞭解了可見性修飾符,我們看一下類的定義,類使用關鍵字class定義

class AClass {

}

這樣我們就定義了一個名稱為AClass的類。該類有一個無參構造器,不需要顯式定義。

類的構造器

類需要通過構造器,才能夠生成對應的物件。Kotlin中構造器分為兩種:首要構造器和次要構造器。首要構造器只有一個,而次要構造器可以有多個,但是次要構造器都要使用首要構造器完成構造後,新增自己的構造過程。下面我們還是採用逐步演化的方式,講解類的構造器。我們的示例是一個Person類,有兩個成員變數姓名(name)和年齡(age),完整的定義如下

class Person1 public constructor(name: String="Monkey", age: Int=12) {

    init {
        println("姓名:$name")
        println("年齡:$age")
    }

    constructor(name: String) : this(name, 15) { }
}

我們定義一個Person1類,緊跟其後的是首要構造器,該構造器的可見性為public,首要構造器有兩個引數,姓名和年齡,且具有預設值。類內部有一個init關鍵字開頭的程式碼塊,這稱之為初始化塊,由於Kotlin的首要構造器不存在函式體,可以在init程式碼塊中加入一些初始化邏輯。類的內部還有一個constructor函式,這就是次要構造器,其後通過this呼叫了首要構造器,次要構造器函式體內為空。

我們定義幾個物件,看看init塊中的列印

//使用有預設引數的建構函式
var person1 = Person1()

//使用完整的首要建構函式
person1 = Person1("Tom", 13)

//使用次要建構函式
person1 = Person1("Jim")

我們定義了三個物件,由於構造物件時必然會呼叫init程式碼塊,所以我們執行後看到結果如下

姓名:Monkey
年齡:12
姓名:Tom
年齡:13
姓名:Jim
年齡:15

前兩個不再過多解釋,主要看一下第三個,我們使用了帶有一個引數的構造器,那麼到底使用的是次要構造器還是首要構造器使用了age的預設引數呢?從結果很容易發現,我們使用的是次要構造器,也就是Kotlin會找到最匹配的構造器使用。

上面的定義太複雜了,我們開始做一些簡化。首先,首要構造器的可見性預設為public,所以,如果可見性為public,我們可以省略可見性描述符。由於可見性描述符被省略了,constructor也可以省略,一起摘掉吧。由於次要構造器沒有函式體,大括號也可以去掉。

class Person2(name: String="Monkey", age: Int=12) {

    init {
        println("Person2 姓名:$name")
        println("Person2 年齡:$age")

        //試圖修改引數值
        //name = "Tom"
    }

    constructor(name: String) : this(name, 15)
}

當然,如果不需要init程式碼塊和引數預設值,也可以去掉。總之,上面的例子基本上可以算作最簡化的類定義了。

最後強調一點,構造器引數預設是隻讀的,不可以對引數進行修改,否則將無法通過編譯,例如嘗試修改常量引數,會編譯報錯

name = “Tom”

如果需要修改,可以在構造器引數前加上修飾符var

class Person3(var name: String="Monkey", age: Int=12) {

    init {
        println("Person3 姓名:$name")
        println("Person3 年齡:$age")

        name = "Tom"
    }

    constructor(name: String) : this(name, 15)
}

但此時name實際上已經不再是構造器引數了,它已經成為了一個類的屬性,而age還是一個構造器引數。關於類的屬性,後續的文章會詳細介紹,現在只需要記住類的屬性可以通過var和val定義其讀寫性。

下面給出一些Kotlin類的概述,後續文章會有更詳細的說明:

1.類可以繼承多個類,可以實現介面;

2.可以定義抽象類;

3.可以定義資料類;

4.可以對已有類進行擴充套件;

5.類的內部可以包含:

——構造器和初始化塊

——方法

——屬性

——內部類

——匿名物件