Kotlin 類 – Kotlin 構造函數

在本教程中,我們將討論Kotlin的面向對象編程概念。我們將詳細討論Kotlin類。我們還將討論Kotlin的構造函數、訪問修飾符和抽象類。

Kotlin類

類是一個定義藍圖,用於分組函數和屬性。在Kotlin中,使用關鍵字class後跟類名來定義類。主體部分放在花括號內。

class FirstClass {
}

可以通過以下方式實例化類:

val firstClass =  FirstClass()
var new = FirstClass() //here new is the name of the var.

與Java不同,Kotlin中沒有new關鍵字。在Kotlin中,類默認是final的。因此,上述Java定義的等價物將如下所示:

public final class FirstClass {
}

因此,默認情況下,Kotlin中的類是不可繼承的。要使類不是final,我們需要添加關鍵字open

open class Me{
}

open註釋允許其他人從這個類繼承。

Kotlin類示例

讓我們創建一個帶有幾個函數和一個屬性的類。我們將看到如何訪問該類的函數和屬性。此外,我們還將看到如何設置成員屬性。

class User {

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"
    
    fun logOn() {
        loggedIn = true
    }
    
    fun logOff() {
        loggedIn = false
    }
}

fun main(args: Array<String>) {

    val user = User()
    println(user.loggedIn) //false
    user.logOn()
    println(user.loggedIn) //true
    user.logOff()
    println(user.loggedIn) //false
    user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.

}

函數main屬於Test.kt類。要訪問成員和函數,我們需要使用點運算符。使用點運算符無法再次設置val屬性。

Kotlin初始化

Kotlin初始化塊的定義如下所示。

class User {
    
    init{
        print("Class instance is initialised.")
    }

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"

    fun logOn() {
        loggedIn = true
    }

    fun logOff() {
        loggedIn = false
    }
}

當類實例化時,首先執行init塊中的代碼。每次類被實例化時,都會運行init塊,無論使用什麼類型的構造函數,我們將在下一節中看到。可以在類中編寫多個初始化塊。它們將按照順序執行,如下所示。

class MultiInit(name: String) {

    init {
        println("First initializer block that prints ${name}")
    }

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {
    var multiInit = MultiInit("Kotlin")
}

//以下在日誌控制台中打印。
//第一個初始化塊打印Kotlin
//第二個初始化塊打印6

Kotlin類允許在聲明本身中使用also函數打印屬性,如下所示。

class MultiInit(name: String) {
    val firstProperty = "First property: $name".also(::println)

    init {
        println("First initializer block that prints ${name}")
    }

    val secondProperty = "Second property: ${name.length}".also(::println)

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {

    var multiInit = MultiInit("Kotlin")
}

//以下將被打印。
//第一個屬性:Kotlin
//第一個初始化塊打印Kotlin
//第二個屬性:6
//第二個初始化塊打印6

Kotlin建構函式

Kotlin建構函式是特殊的成員函式,用於初始化屬性。 Kotlin中的建構函式與Java相比具有不同的寫法和結構。 默認情況下,類具有空建構函式,如下所示:

class Student {
    var name: String
    val age : Int

    init {
        name = "Anupam"
        age = 24
    }

    init {
        name = "Anupam Chugh"
        //age = 26
    }
}

fun main(args: Array) {
    
    val student = Student()
    println("${student.name} age is ${student.age}")
    student.name = "Your"
    //student.age = 26 //無法編譯。 age是val
    println("${student.name} age is ${student.age}")

}

//以下內容將顯示在控制台上:
//Anupam Chugh age is 24
//Your age is 24

主要建構函式

Kotlin中的主要建構函式是在類標頭中定義的,如下所示。

class User(var name: String, var isAdmin: Boolean) {

    init {
        name = name + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $isAdmin")
    }
}

主要建構函式的定義放在類標頭內部。 我們在建構函式中定義了屬性類型(val/var)。注意:除非被聲明為var,否則默認情況下,建構函式引數是val

class User(name: String, isAdmin: Boolean)

在上面的代碼中,name和isAdmin都無法重新賦值。 或者,我們也可以將建構函式引數分配給類中的成員屬性,如下所示。

class User(name: String, val isAdmin: Boolean) {

    var username  = name
    val _isAdmin = isAdmin

    init {
        username= username + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $_isAdmin")
    }
}

fun main(args: Array) {

    var user = User("Anupam",false)
    user.isAdmin = true //won't compile since isAdmin is val
    user._isAdmin = true //won't compile. Same reason.
    user = User("Pankaj",true)
}

//以下內容將在日誌控制台中打印。
//作者名稱是Anupam。 是否為管理員? false
//作者名稱是Pankaj。 是否為管理員? true

Kotlin 建構子預設值

Kotlin 允許我們在建構子本身中指定預設值,如下所示。

class User(name: String, var website: String = "JournalDev") {

    init {
        println("Author $name writes at $website")
    }

    init {
        website = website + ".com"
        println("Author $name writes at $website")
    }
}

fun main(args: Array) {

    var user = User("Anupam","JournalDev")
    user = User("Pankaj","JournalDev")
}

//以下內容會在控制台上輸出:
//作者 Anupam 在 JournalDev 上撰寫
//作者 Anupam 在 JournalDev 上撰寫.com
//作者 Pankaj 在 JournalDev 上撰寫
//作者 Pankaj 在 JournalDev 上撰寫.com

次要建構子

次要建構子是在類別本身內部以 constructor 關鍵字為前綴撰寫的。以下示例演示了相同的情況。

class Student {
    var name: String
    val age : Int

    constructor(name: String, age: Int)
    {
        this.name = name
        this.age = age
    }

    fun printDetails()
    {
        println("Name is $name and Age is $age")
    }

}

fun main(args: Array) {

    var student = Student("Anupam", 24)
    student.printDetails()
}

//以下內容會在控制台上輸出:
//姓名為 Anupam,年齡為 24 歲

次要建構子最常見的用法是在子類別中,當您需要以不同方式初始化類別時。如果類別包含主要建構子,則次要建構子必須在其宣告中參考它。宣告是使用 this 關鍵字完成的。

class Student(var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

//以下內容會在日誌控制台上輸出:
//姓名為 Anupam,年齡為 24 歲
//姓名為 Anupam,年齡為 24 歲 Skill is Kotlin

init區塊用於初始化成員屬性skill。次要建構子使用: this委派給主要建構子。

自定義 Getter 和 Setter

迄今為止,我們使用類的實例上的點運算符來訪問和修改類中的屬性。讓我們使用setget語法,看看如何自定義訪問。

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
                print(value)
    }

}

fun main(args: Array<String>) {

    var name = Name()
    name.post = "Kotlin Classes"
    name.post = ""
    name.post = "Kotlin Data Classes Our Next Tutorial"


}

以下內容會印在日誌控制台上:

Kotlin Classes

Exception in thread "main" java.lang.IllegalArgumentException:  Enter a valid name
	at Name.setPost(Test.kt:16)
	at TestKt.main(Test.kt:78)

在 Setter 中的field變數保存了舊值。讓我們添加一個 Getter。

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
    }
    get() {
        return field.capitalize()
    }

}

fun main(args: Array) {

    var name = Name()
    name.post = "kotlin classes"
    println(name.post)
    name.post = "kotlin data Classes our next Tutorial"
    println(name.post)

}

//以下內容會印出:
//Kotlin 類
//Kotlin 數據類是我們下一個教程

capitalize()將字符串的第一個字母大寫。 注意: 如果屬性是valset方法將無法編譯。

Kotlin 可見性修飾符

  • Public: 具有此修飾符的任何類、函數、屬性、接口或對象都是可見的,可以從任何地方訪問。
  • 私有:使用此修飾詞定義的類別/函數僅能在同一檔案中存取。在具有此修飾詞的類別/函數中的成員/屬性僅能在該區塊內存取。
  • 保護:此修飾詞與私有相同,唯一的不同是它允許在子類別中可見並存取。
  • 內部:具有此修飾詞的類別/介面/函數僅能在同一模組中存取。

可見性修飾詞也適用於建構函數。將修飾詞分配給主要建構函數需要我們在類別標頭中指定關鍵字 constructor 以及建構函數。

class Student private constructor (var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

fun main(args: Array) {

    var student = Student("Anupam",24,"Kotlin")
    student.printDetails()
}

//prints
//名稱是 Anupam 而年齡是 24,技能是 Kotlin

私有建構函數無法在類別外部調用。在上述程式碼中,我們只能使用次要建構函數在不同函數中實例化該類別。

Kotlin 抽象類別

與 Java 類似,abstract 關鍵字用於在 Kotlin 中宣告抽象類別。抽象類別無法被實例化,但可以被子類別繼承。預設情況下,抽象類別的成員是非抽象的,除非另有聲明。

abstract class Person(name: String) {

    init {
        println("Abstract Class. init block. Person name is $name")
    }

    abstract fun displayAge()
}

class Teacher(name: String): Person(name) {

    var age : Int

    init {
        age = 24
    }

    override fun displayAge() {
        println("Non-abstract class displayAge function overridden. Age is $age")
    }
}

fun main(args: Array) {

    val person = Teacher("Anupam")
    person.displayAge()

}

//以下內容會被列印在控制台中。
//抽象類別。初始化區塊。人名是 Anupam
//非抽象類別。年齡是 24

注意:抽象類別預設為open。因此,不需要添加open修飾符以允許子類別化。override關鍵字用於覆蓋子類別中的方法。我們在本教程中已經介紹了 Kotlin 類別的基礎知識。還有許多其他內容,例如資料類別、密封類別、繼承等等。我們將在接下來的教程中涵蓋它們。參考資料:Kotlin 文檔

Source:
https://www.digitalocean.com/community/tutorials/kotlin-class-constructor