Kotlin基礎(3)-->面向對象編程 一、類與對象 二、繼承與構造函數

一、類與對象

首先創建一個人類

class Person {
    var name = ""
    var age = 0
    fun eat() {
        println(name + " is eating. He is " + age + " years old.")
    }
}

可以看到。Kotlin中也是使用class關鍵字來聲明一個類的。接下來我們對這個類進行實例化

fun main() {
    val person = Person()
    person.age = 10
    person.name = "A"
    person.eat()
    //打印結果:A is eating. He is 10 years old.
}

Kotlin實例化一個類的方式與Java類似,只是去掉了new關鍵字。

二、繼承與構造函數

1.繼承

與Java不同的是,在Kotlin中任何一個非抽象類默認都是不可被繼承的,如果想讓他變得可以被繼承,就在類的前面加上open關鍵字。

open class Person {
   ...
}

創建一個Student類使用 : 關鍵字繼承Person類

class Student : Person() {
    var sno = ""
    var grade = 0
}

到這裏大家可能會有疑問,爲什麼Person類後面要加上()呢?繼續學習下面部分。

2.主構造函數

主構造函數是我們最常用的構造函數,每個類默認都會有一個不帶參數的主構造函數,例如剛纔我們定義的Person和Student類。當然我們也可以顯示的給它指明參數,直接定義在類名後面即可,如下所示:

open class Person(val name: String, val age: Int) {
    fun eat() {
        println(name + " is eating. He is " + age + " years old.")
    }
}

之後我們在實例化Person時,就必須傳入構造函數中所有要求的函數。
主構造函數特點就是沒有函數體,那麼我們想在主構造函數中編寫一些邏輯的話,就需要使用init結構體,個人認爲有點類似於Java中的靜態代碼塊。

open class Person(val name: String, val age: Int) {
    init {
        println(name + " is eating. He is " + age + " years old.")
    }
}

fun main() {
    val person = Person("A",10)
    //打印結果:A is eating. He is 10 years old.
}

此時我們的StudentL類會報錯,因爲我們已經Person中已經沒有無參構造函數了。這個時候我們就明白剛纔那個()的含義和作用了吧:
Java繼承特性規定,子類構造函數必須調用父類構造函數,而主構造函數並沒有函數體,如何去調用父類的構造函數呢?你可能會說在init中調用,這並不是一種好辦法,因爲大多數情況下我們並不需要編寫init結構體的,所以,Kotlin採用了一種簡單但是不好理解的方式:括號。子類的主構造函數調用父類的哪個構造函數,在繼承的時候通過括號來指定。

回到最開始,Person中並沒有顯式的指明參數,只有一種默認的無參構造函數,所以Student在繼承Person時寫個空括號就可以了,但是之後我們給Person顯式的指明瞭參數,所以Student再使用空括號就會報錯了,因爲Person已經沒有無參構造函數了,接下來我們修改一下Student類

class Student(val sno: String, val grade: Int, name: String, age: Int) 
    : Person(name, age) {
}

注意:我們在Student類的主構造函數中增加name,age字段時,不能再將他們聲明爲val,因爲在主構造函數中聲明成var或者val的參數將自動成爲該類的字段,這就會導致和父類中同名的name,age字段衝突。因此,name和age前面不用加任何關鍵字,讓他的作用域只限於主構造函數中即可

Kotlin在括號這個問題上的複雜度並不僅限於此,接下來我們來學習次構造函數

3.次構造函數

任何一個類只能有一個主構造函數,但是可以有多個次構造函數。次構造函數也可以用來實例化一個類,並且它是有函數體的。
Kotlin規定,當一個類既有主構造函數又有次構造函數時,所有的次構造函數都必須調用主構造函數(包括間接調用)

class Student(var sno: String, var grade: Int, name: String, age: Int) : Person(name, age) {
    constructor(name: String, sno: String) : this("", 0, "", 0) {
    }
    constructor() : this("", "") {
    }
}

次構造函數通過constructor關鍵字定義,第一個次構造函數使用this關鍵字調用了主構造函數,第二個次構造函數使用this關鍵字調用了第一個次構造函數,相當於間接調用了主構造函數。
此時我們就有了3中實例化Student的方式。

    val student1 = Student()
    val student2 = Student("A", "22")
    val student3 = Student("22", 1, "A", 10)

接下來我們說一種特殊情況:類中只有次構造函數沒有主構造函數。
當一個類沒有顯示的定義主構造函數且定義了次構造函數時,它其實就是沒有主構造函數的。

class Student: Person{
    constructor(name: String, sno: String) : super("", 0) {
    }
}

由於沒有主構造函數,次構造函數只能直接調用父類的構造函數,將this關鍵字換成了super關鍵字。
既然Student沒有主構造函數,繼承Person時也不需要加上括號了。
這就知道爲什麼有時要加括號,有時又不加括號了吧。

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