首页 > 解决方案 > Kotlin 构造函数语法设计原理?

问题描述

在我看来,这两个类的行为相同:

class A constructor(ii_: Int) {
    var ii = 0
    var xx = 0.0F
    var msg = ""
    init {
        ii = ii_
        xx = ii + 42.0F
        msg = "The value of ii is $ii and the value of xx is $xx"
    }
    
    fun display() {
        print("A.display() $ii, $xx\n")
        print("A.display() $msg\n")
    }
    
}


class C {
    var ii = 0
    var xx = 0.0F
    var msg = ""
    constructor(ii_: Int) {
        ii = ii_
        xx = ii + 42.0F
        msg = "The value of ii is $ii and the value of xx is $xx"
    }
    
    fun display() {
        print("C.display() $ii, $xx\n")
        print("C.display() $msg\n")
    }
    
}

如果我不会有多个构造函数,那么使用主构造函数的版本是否有优势?

是否存在我没​​有看到主要 ctor + init 块方案的理论原因?

带有它的 init 块的主要构造函数版本看起来很巴洛克,这让我认为它有更深层次的原因,但我看不到它。

我知道我的 A 类并不严格需要构造函数关键字。那不是我要问的,请不要打扰告诉我我不需要它。

标签: kotlinconstructor

解决方案


init块更像是属性初始化器而不是构造器。(如果您了解 Java,它们与 Java 的实例初始化程序几乎相同;请参阅此问题此讨论。)主要问题是:

  • 你可以有多个init块;它们都按顺序运行(连同属性初始化表达式)。如果您使用它们来初始化属性,为了清楚起见,您可以将它们放在它们的属性旁边。

  • 它们为每个构造函数运行,因此您无需在构造函数之间复制代码,或者冒着忘记的风险。(它们与属性初始化器一起在调用超类构造函数之后但在构造函数主体的其余部分之前运行。)

  • 它们可以在object不允许使用构造函数的表达式和声明中使用。(它们最初被引入 Java 是为了等效于这个,即匿名类。)

  • 如果有一个主构造函数,那么它们就可以访问它的参数(尽管不能访问任何辅助构造函数的参数)。(这使得它们比 Java 的实例初始化器更强大。)


推荐阅读