Kotlin 构造函数(Constructor)
在本文中,您将在示例的帮助下了解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 类的对象时,将传递值 Joe 和 25,就好像Person是一个函数一样。
这将 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 //初始化块 init { firstName = fName.capitalize() age = personAge println("First Name = $firstName") println("Age = $age") } }
运行该程序时,输出为:
First Name = Joe Age = 25
这里,在创建 person1对象时,圆括号内的参数 fName 和 personAge 分别接受值 "Joe" 和 25。但是,使用 fName 和 personAge 时不使用 var 或 val,而且它们不是 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 //初始化块 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 // 初始化块 init { ... .. ... } }
主构造函数中的默认值
您可以为构造函数参数提供默认值(类似于为函数提供默认参数)。例如:
fun main(args: Array<String>) { println("person1 被实例化") val person1 = Person("joe", 25) println("person2 被实例化") val person2 = Person("Jack") println("person3 被实例化") val person3 = Person() } class Person(_firstName: String = "UNKNOWN", _age: Int = 0) { val firstName = _firstName.capitalize() var age = _age //初始化块 init { println("First Name = $firstName") println("Age = $age\n") } }
运行该程序时,输出为:
First Name = Joe Age = 25 person2 被实例化 First Name = Jack Age = 0 person3 被实例化 First Name = UNKNOWN Age = 0
Kotlin 次构造函数
在Kotlin中,一个类还可以包含一个或多个次构造函数。它们是使用 constructor 关键字创建的。
次构造函数在Kotlin中并不常见。 当您需要扩展提供以不同方式初始化类的多个构造函数的类时,次要构造函数的最常见用法就出现了。在学习之前,请确认已经了解Kotlin继承。
您可以在Kotlin中创建次构造函数的方法如下:
class Log { constructor(data: String) { // 一些代码 } constructor(data: String, numberOfData: Int) { // 一些代码 } }
在这里,Log 类具有两个次构造函数,但没有主要构造函数。
您可以将类扩展为:
class Log { constructor(data: String) { // 代码 } constructor(data: String, numberOfData: Int) { // 代码 } } class AuthLog: Log { constructor(data: String): super(data) { // 代码 } constructor(data: String, numberOfData: Int): super(data, numberOfData) { // 代码 } }
在此,派生类 AuthLog 的构造函数调用基类 Log 的相应构造函数。为此,使用 super()。
在Kotlin中,您还可以使用 this() 来从同一类的另一个构造函数(如Java中)调用构造函数。
class AuthLog: Log { constructor(data: String): this(data, 10) { // 代码 } constructor(data: String, numberOfData: Int): super(data, numberOfData) { // 代码 } }
示例: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
注意:如果类没有主构造函数,则次构造函数必须将基类或委托初始化为另一个构造函数(如上例所示)。