原文: https://www.programiz.com/kotlin-programming/constructors
在本文中,您将通过示例了解 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<String>) {
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
对象的firstName
和age
属性分别初始化为"Joe"
和25
。
还有其他使用主要构造器的方法。
主构造器和初始化块
主构造器的语法受约束,不能包含任何代码。
为了放置初始化代码(不仅是用于初始化属性的代码),使用了初始化块。 它以init
关键字为前缀。 让我们使用初始化块修改以上示例:
fun main(args: Array<String>) {
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
对象时,括号内的参数fName
和personAge
分别接受值"Joe"
和25
。 但是,不使用var
或val
而使用fName
和personAge
,它们不是Person
类的属性。
Person
类具有两个属性firstName
,并且声明了age
。
创建person1
对象时,将执行初始化块内的代码。 初始化块不仅初始化其属性,还打印它们。
这是执行相同任务的另一种方法:
fun main(args: Array<String>) {
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")
}
}
为了区分构造器参数和属性,使用了不同的名称(fName
和firstName
,以及personAge
和age
)。 对于构造器参数,使用_firstName
和_age
更为常见。 例如:
class Person(_firstName: String, _age: Int) {
val firstName = _firstName.capitalize()
var age = _age
// initializer block
init {
... .. ...
}
}
主构造器中的默认值
您可以为构造器参数提供默认值(类似于为函数提供默认参数)。 例如:
fun main(args: Array<String>) {
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<String>) {
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
注意:如果该类没有主构造器,则辅助构造器必须初始化基类或委托给另一个构造器(如上例所示)。