📜  Kotlin构造函数

📅  最后修改于: 2020-10-05 14:42:18             🧑  作者: Mango

在本文中,您将在示例的帮助下了解Kotlin中的构造函数(主要构造函数和辅助构造函数)以及初始化程序块。

构造函数是初始化类属性的简洁方法。

它是一个特殊的成员 函数 ,在实例化(创建)对象时调用。但是,它们在Kotlin中的工作方式略有不同。

在Kotlin中,有两个构造函数:

  • 主构造函数 -初始化类的简洁方法
  • 辅助构造函数 -允许您放置其他初始化逻辑

主要建设者

主构造函数是类标头的一部分。这是一个例子:

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

用括号括起来的代码块是主要的构造函数: (val firstName: String, var age: Int)

构造函数声明了两个属性: firstName (使用关键字val声明的只读属性)和age (使用关键字var声明的读写属性)。


示例:主构造函数

fun main(args: Array) {

    val person1 = Person("Joe", 25)

    println("First Name = ${person1.firstName}")
    println("Age = ${person1.age}")
}

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

}

运行该程序时,输出为:

First Name = Joe
Age = 25

创建Person类的对象时,就像Person是一个函数一样,传递了"Joe"25值。

会将person1对象的firstNameage属性分别初始化为"Joe"25


还有其他使用主要构造函数的方法。


主构造器和初始化器块

主构造函数的语法受约束,不能包含任何代码。

为了放置初始化代码(不仅是初始化属性的代码),使用了初始化程序块。它以init关键字为前缀。让我们用初始化程序块修改以上示例:

fun main(args: Array) {
    val person1 = Person("joe", 25)
}

class Person(fName: String, personAge: Int) {
    val firstName: String
    var age: Int

    // initializer block
    init {
        firstName = fName.capitalize()
        age = personAge

        println("First Name = $firstName")
        println("Age = $age")
    }
}

运行该程序时,输出为:

First Name = Joe
Age = 25

在此,创建person1对象时,括号内的参数fNamepersonAge分别接受值"Joe"25 。但是,使用fNamepersonAge时不使用varval ,它们不是Person类的属性。

Person类具有两个属性firstName ,并且声明了age

创建person1对象时,将执行初始化程序块内的代码。初始化程序块不仅初始化其属性,还打印它们。


这是执行相同任务的另一种方法:

fun main(args: Array) {
    val person1 = Person("joe", 25)
}

class Person(fName: String, personAge: Int) {
    val firstName = fName.capitalize()
    var age = personAge

    // initializer block
    init {
        println("First Name = $firstName")
        println("Age = $age")
    }
}

为了区分构造函数的参数和属性,使用了不同的名称( fNamefirstName ,以及personAgeage )。对于构造函数参数,使用_firstName_age而不是完全不同的名称更为常见。例如:

class Person(_firstName: String, _age: Int) {
    val firstName = _firstName.capitalize()
    var age = _age

    // initializer block
    init {
        ... .. ...
    }
}

主构造函数中的默认值

您可以为构造函数参数提供默认值(类似于为函数提供默认参数)。例如:

fun main(args: Array) {

    println("person1 is instantiated")
    val person1 = Person("joe", 25)

    println("person2 is instantiated")
    val person2 = Person("Jack")

    println("person3 is instantiated")
    val person3 = Person()
}

class Person(_firstName: String = "UNKNOWN", _age: Int = 0) {
    val firstName = _firstName.capitalize()
    var age = _age

    // initializer block
    init {
        println("First Name = $firstName")
        println("Age = $age\n")
    }
}

运行该程序时,输出为:

First Name = Joe
Age = 25

person2 is instantiated
First Name = Jack
Age = 0

person3 is instantiated
First Name = UNKNOWN
Age = 0

Kotlin二级构造器

在Kotlin中,一个类还可以包含一个或多个辅助构造函数。它们是使用constructor关键字创建的。

二级构造函数在Kotlin中并不常见。当您需要扩展一个提供多个以不同方式初始化该类的构造函数的类时,就会出现辅助构造函数的最常见用法。在学习之前,请务必检查Kotlin继承。

您可以在Kotlin中创建辅助构造函数的方法如下:

class Log {
    constructor(data: String) {
        // some code
    }
    constructor(data: String, numberOfData: Int) {
        // some code
    }
}

在这里, Log类具有两个辅助构造函数,但没有主要构造函数。

您可以将类扩展为:

class Log {
    constructor(data: String) {
        // code
    }
    constructor(data: String, numberOfData: Int) {
        // code
    }
}

class AuthLog: Log {
    constructor(data: String): super(data) {
        // code
    }
    constructor(data: String, numberOfData: Int): super(data, numberOfData) {
        // code
    }
}

在此,派生类AuthLog的构造函数调用基类Log的相应构造函数。为此,使用了super()

从派生类调用基类的构造函数。

在Kotlin中,您还可以使用this()从同一个类的另一个构造函数(如Java)中调用构造函数。

class AuthLog: Log {
    constructor(data: String): this(data, 10) {
        // code
    }
    constructor(data: String, numberOfData: Int): super(data, numberOfData) {
        // code
    }
}

从同一类调用构造函数。


示例:Kotlin二级构造函数

fun main(args: Array) {

    val p1 = AuthLog("Bad Password")
}

open class Log {
    var data: String = ""
    var numberOfData = 0
    constructor(_data: String) {

    }
    constructor(_data: String, _numberOfData: Int) {
        data = _data
        numberOfData = _numberOfData
        println("$data: $numberOfData times")
    }
}

class AuthLog: Log {
    constructor(_data: String): this("From AuthLog -> " + _data, 10) {
    }

    constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) {
    }
}

运行该程序时,输出为:

From AuthLog -> Bad Password: 10 times

注意:如果该类没有主构造函数,则辅助构造函数必须初始化基类或委托给另一个构造函数(如上例所示)。