Kotlin构造函数:主构造函数和次构造函数

4
我刚开始学习Kotlin,其中你可以有一个主要构造函数和一个或多个次要构造函数。这个问题听起来很简单,但我找不到答案(我已经阅读了文档中的“构造函数”部分)-为什么?基本上,我试图理解主要和次要之间的区别以及它们在使用上的区别(似乎没有,那么为什么要分离)?

2
一个主要的区别是所有的次要构造函数最终都必须委托给主构造函数。 - Oliver Charlesworth
@OliverCharlesworth 谢谢!这听起来非常合乎逻辑和简单,我不明白为什么一开始就没有理解。 - khusrav
3个回答

6

有明显的语法差异。但一个主要的概念上的区别在于,所有的次要构造函数最终都会委托给主构造函数。

我认为这样理解:主构造函数是创建对象的规范接口,而次要构造函数则像是静态助手,用于将其他参数集转换为符合此接口的参数集。*


*请注意,这是个人解释,没有任何官方文档支持!


我倾向于同意你的“个人解释”。所有其他差异似乎不需要主要/次要区分。 - khusrav

3

主构造函数

  • Kotlin类只能有一个主构造函数
  • 主构造函数提供了一种简单的方式来初始化类的成员属性。
  • 它接受一个逗号分隔的参数列表,并在类名称后作为头部的一部分声明。
// How to declare a primary constructor
class Student constructor(
    firstName: String,
    lastName: String
) {
}

// We can omit constructor keyword if the primary constructor
// does not have any annotations or visibility modifiers

class Student(
    firstName: String,
    lastName: String
) {
}

fun main() {
    val student1 = Student("Helen", "trump")
}
  • Kotlin的主构造函数语法有所限制,仅用于声明类属性,不接受任何逻辑或代码。因此,为了弥补这一空白,Kotlin提供了一个灵活的初始化块的概念,在其中可以添加更多自定义代码来执行一些逻辑!
class Student(
    firstName: String,
    lastName: String
) {
    init {
        println("Welcome to the student profile")
    }
}
  • 这些初始化块在主构造函数调用后、任何次要构造函数之前执行。

次要构造函数

  • Kotlin类可以拥有一个或多个次要构造函数
  • 它们必须以关键字 constructor 为前缀。
  • 我们不能像在主构造函数中那样在次要构造函数中声明类属性。
  • 每个次要构造函数必须明确调用主构造函数。我们可以使用this关键字来实现。
class Pizza constructor (
    var crustSize: String,
    var crustType: String,
    val toppings: MutableList<String> = mutableListOf()
) {

    // secondary constructor (no-args)
    constructor() : this("SMALL", "THIN")

    // secondary constructor (2-args)
    constructor(crustSize: String, crustType: String) : this(crustSize, crustType, mutableListOf<String>())

    override fun toString(): String = "size: ${crustSize}, type: ${crustType}, toppings: ${toppings}"

}

fun main(args: Array<String>) {
    val p1 = Pizza()
    val p2 = Pizza("LARGE", "THICK")
    val p3 = Pizza("MEDIUM", "REGULAR", mutableListOf("CHEESE", "PEPPERONI"))

    println(p1)
    println(p2)
    println(p3)
}

输出:

size: SMALL, type: THIN, toppings: []
size: LARGE, type: THICK, toppings: []
size: MEDIUM, type: REGULAR, toppings: [CHEESE, PEPPERONI]

Reference


初始化块(init {...})运行在主构造函数之后并不完全正确。初始化块在主构造函数期间运行,并且可以与属性初始化器交错运行。两者按照它们在类体中出现的顺序运行。详见Classes - Silvio Mayolo

0

Kotlin的主构造函数帮助您编写简洁的代码:

  • 你可以写没有主体的类,例如:data class,例如:

    data class Data(val value:String)
    
  • 如果构造函数上没有任何注释,则关键字constructor可以省略。一个负面的例子:

    class Foo @Annotation constructor()
    
  • 它使继承变得简单,例如:

    open class Bar(val value: String);
    
    class Primary(value: String, other: String) : Bar(value)
    
    class Secondary : Bar {
        constructor(value: String, other: String) : super(value)
    }
    
  • 它可以使用关键字by进行委托,但是次要构造函数不能使用。

    interface Rule {
        fun apply(value: String): Int
    }
    
    
    open class Policy(rule: Rule) : Rule by rule;
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接