原文: https://www.programiz.com/kotlin-programming/constructors

在本文中,您将通过示例了解 Kotlin 中的构造器(主要构造器和辅助构造器)以及初始化块。

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

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

在 Kotlin 中,有两个构造器:

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

主要构造器

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

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

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

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


示例:主要构造器

  1. fun main(args: Array<String>) {
  2. val person1 = Person("Joe", 25)
  3. println("First Name = ${person1.firstName}")
  4. println("Age = ${person1.age}")
  5. }
  6. class Person(val firstName: String, var age: Int) {
  7. }

运行该程序时,输出为:

  1. First Name = Joe
  2. Age = 25

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

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


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


主构造器和初始化块

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

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

  1. fun main(args: Array<String>) {
  2. val person1 = Person("joe", 25)
  3. }
  4. class Person(fName: String, personAge: Int) {
  5. val firstName: String
  6. var age: Int
  7. // initializer block
  8. init {
  9. firstName = fName.capitalize()
  10. age = personAge
  11. println("First Name = $firstName")
  12. println("Age = $age")
  13. }
  14. }

运行该程序时,输出为:

  1. First Name = Joe
  2. Age = 25

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

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

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


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

  1. fun main(args: Array<String>) {
  2. val person1 = Person("joe", 25)
  3. }
  4. class Person(fName: String, personAge: Int) {
  5. val firstName = fName.capitalize()
  6. var age = personAge
  7. // initializer block
  8. init {
  9. println("First Name = $firstName")
  10. println("Age = $age")
  11. }
  12. }

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

  1. class Person(_firstName: String, _age: Int) {
  2. val firstName = _firstName.capitalize()
  3. var age = _age
  4. // initializer block
  5. init {
  6. ... .. ...
  7. }
  8. }

主构造器中的默认值

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

  1. fun main(args: Array<String>) {
  2. println("person1 is instantiated")
  3. val person1 = Person("joe", 25)
  4. println("person2 is instantiated")
  5. val person2 = Person("Jack")
  6. println("person3 is instantiated")
  7. val person3 = Person()
  8. }
  9. class Person(_firstName: String = "UNKNOWN", _age: Int = 0) {
  10. val firstName = _firstName.capitalize()
  11. var age = _age
  12. // initializer block
  13. init {
  14. println("First Name = $firstName")
  15. println("Age = $age\n")
  16. }
  17. }

运行该程序时,输出为:

  1. First Name = Joe
  2. Age = 25
  3. person2 is instantiated
  4. First Name = Jack
  5. Age = 0
  6. person3 is instantiated
  7. First Name = UNKNOWN
  8. Age = 0

Kotlin 二级构造器

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

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

这是您可以在 Kotlin 中创建辅助构造器的方法:

  1. class Log {
  2. constructor(data: String) {
  3. // some code
  4. }
  5. constructor(data: String, numberOfData: Int) {
  6. // some code
  7. }
  8. }

此处,Log类具有两个辅助构造器,但没有主要构造器。

您可以将类扩展为:

  1. class Log {
  2. constructor(data: String) {
  3. // code
  4. }
  5. constructor(data: String, numberOfData: Int) {
  6. // code
  7. }
  8. }
  9. class AuthLog: Log {
  10. constructor(data: String): super(data) {
  11. // code
  12. }
  13. constructor(data: String, numberOfData: Int): super(data, numberOfData) {
  14. // code
  15. }
  16. }

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

Kotlin 构造器 - 图1

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

  1. class AuthLog: Log {
  2. constructor(data: String): this(data, 10) {
  3. // code
  4. }
  5. constructor(data: String, numberOfData: Int): super(data, numberOfData) {
  6. // code
  7. }
  8. }

Kotlin 构造器 - 图2


示例:Kotlin 二级构造器

  1. fun main(args: Array<String>) {
  2. val p1 = AuthLog("Bad Password")
  3. }
  4. open class Log {
  5. var data: String = ""
  6. var numberOfData = 0
  7. constructor(_data: String) {
  8. }
  9. constructor(_data: String, _numberOfData: Int) {
  10. data = _data
  11. numberOfData = _numberOfData
  12. println("$data: $numberOfData times")
  13. }
  14. }
  15. class AuthLog: Log {
  16. constructor(_data: String): this("From AuthLog -> " + _data, 10) {
  17. }
  18. constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) {
  19. }
  20. }

运行该程序时,输出为:

  1. From AuthLog -> Bad Password: 10 times

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