Kotlin 构造函数关键字
最后修改于 2025 年 4 月 19 日
Kotlin 提供了通过构造函数初始化类的灵活方式。 constructor
关键字用于定义主构造函数和次构造函数。本教程通过实际示例深入探讨构造函数。
基本定义
在 Kotlin 中,构造函数是一个特殊的成员函数,用于初始化类的实例。有两种类型:主构造函数(在类头中定义)和次构造函数(在类体中定义)。对于没有注解或可见性修饰符的主构造函数,constructor
关键字是可选的。
主构造函数
主构造函数在类头中声明。 它可以包含成为类属性的参数。 如果没有注解或修饰符,这里的构造函数关键字是可选的。
package com.zetcode class Person constructor(val name: String, val age: Int) fun main() { val person = Person("John Doe", 30) println("${person.name} is ${person.age} years old") // Output: John Doe is 30 years old }
此示例显示了一个带有两个参数的主构造函数。 val
关键字使它们成为不可变属性。 我们创建一个 Person 实例并直接访问其属性。
没有关键字的主构造函数
当主构造函数没有注解或可见性修饰符时,为了更简洁的语法,可以省略 constructor
关键字。
package com.zetcode class Person(val name: String, val age: Int) fun main() { val person = Person("Jane Smith", 25) println("${person.name} is ${person.age} years old") // Output: Jane Smith is 25 years old }
这是声明主构造函数最常见的方式。 参数会自动成为类属性。 语法简洁明了,同时提供相同的功能。
带有初始化块的主构造函数
init
块允许在创建对象期间执行代码。它在评估主构造函数参数之后但在任何次构造函数之前运行。
package com.zetcode class Person(name: String, val age: Int) { val name: String init { this.name = name.capitalize() println("Person initialized: $name") } } fun main() { val person = Person("alice", 28) println("${person.name} is ${person.age}") // Output: Person initialized: alice // Alice is 28 }
在这里,我们在将 name 参数分配给属性之前,在 init 块中处理它。 init 块可以包含类所需的任何初始化逻辑。 多个 init 块按出现的顺序执行。
次构造函数
次构造函数使用 constructor
关键字在类体中定义。如果存在主构造函数,它们必须委托给主构造函数。
package com.zetcode class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) { println("Secondary constructor used") } } fun main() { val person1 = Person("Bob", 40) val person2 = Person("Charlie") println("${person2.name} is ${person2.age}") // Output: Secondary constructor used // Charlie is 0 }
次构造函数提供默认年龄 0。它必须使用 this
调用主构造函数。 次构造函数对于多个初始化路径很有用,同时保持单个主初始化。
带有可见性修饰符的构造函数
指定可见性修饰符时,需要 constructor
关键字。这控制了可以从其他代码访问构造函数的方式。
package com.zetcode class Person private constructor(val name: String) { companion object { fun create(name: String): Person { return Person(name) } } } fun main() { val person = Person.create("Admin") println(person.name) // Output: Admin }
这里,主构造函数是私有的,因此必须通过伴生对象中的工厂方法创建实例。 这是一种用于控制对象创建的常见模式,例如在单例实现中。
多个次构造函数
一个类可以有多个次构造函数,每个构造函数都提供了不同的初始化对象的方式。 所有构造函数最终都必须委托给主构造函数。
package com.zetcode class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) constructor(age: Int) : this("Anonymous", age) } fun main() { val person1 = Person("Dave") val person2 = Person(35) println("${person1.name} is ${person1.age}") println("${person2.name} is ${person2.age}") // Output: Dave is 0 // Anonymous is 35 }
此类提供了三种创建实例的方式:同时使用 name 和 age,仅使用 name(默认年龄),或仅使用 age(默认名称)。 每个次构造函数都提供不同的默认值,同时保持一致性。
带有默认值的构造函数
Kotlin 允许为构造函数参数指定默认值,通常不需要次构造函数。 这提供了灵活的初始化选项。
package com.zetcode class Person( val name: String = "Guest", val age: Int = 0 ) fun main() { val person1 = Person() val person2 = Person("Eve") val person3 = Person(age = 30) println("${person1.name} is ${person1.age}") println("${person2.name} is ${person2.age}") println("${person3.name} is ${person3.age}") // Output: Guest is 0 // Eve is 0 // Guest is 30 }
默认参数允许使用任意参数组合创建对象。 命名参数使跳过参数时的代码更具可读性。 对于更简单的情况,这种方法通常优于多个构造函数。
构造函数的最佳实践
- 首选主构造函数: 尽可能使用带有默认值的主构造函数以获得更简洁的代码。
- 明智地使用 init 块: 将初始化逻辑保持在 init 块中,使其简单并专注于设置。
- 限制次构造函数: 仅在真正需要多个初始化路径时才添加次构造函数。
- 考虑使用工厂函数: 对于复杂的初始化,考虑使用伴生对象工厂函数,而不是使用多个构造函数。
- 使用有意义的默认值: 选择对领域有意义并提供良好默认值的默认值。
来源
本教程深入探讨了 Kotlin 的 constructor
关键字,展示了主构造函数和次构造函数的使用。 我们探讨了各种初始化模式,包括默认值、init 块和可见性修饰符。 正确使用构造函数可以使类设计更易于维护和更灵活。
作者
列出 所有 Kotlin 教程。