什么是Kotlin类初始化语义?

Nig*_*Eke 14 constructor initialization class kotlin

我无法在语言定义中找到解释Kotlin中类的初始化的任何内容.

import java.util.Properties

fun main(args: Array<String>) {
    val out = MyClass()
    out.fn()
}

class MyClass {
    private val a = Properties() // 1

    init {
        fn()
    }

    public fun fn() {
        println("Fn called.  a = $a")
    }

    //  private val a = Properties() // 2
}
Run Code Online (Sandbox Code Playgroud)

运行此程序的结果会根据属性是在(1)还是在(2)初始化而更改.

我很惊讶声明顺序与语言相关,并且想了解这背后的决定.我的期望是在调用构造函数体之前初始化属性.

aga*_*aga 15

我的期望是在调用构造函数体之前初始化属性.

好吧,init块不是构造函数.它是一个不同的结构,允许您执行对象的初始化,它们[init blocks]以声明顺序与属性初始值设定项一起执行.

构造函数是一个不同的野兽蚂蚁,它们在初始化所有属性并执行所有初始化块后执行.请看以下示例:

class A(val value: Int) {
    constructor(): this(0) {        
        println("Constructor")
    }    

    init {
        println("Init block")
    }
}

fun main(args: Array<String>) {
    val a = A()
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Init block  
Constructor
Run Code Online (Sandbox Code Playgroud)

您可以将init块放在任何地方:在constructor它之前或之后; 它总是被执行之前A的构造(二次构造,在这个例子).

  • 这不完全正确.`init`块包含主构造函数中包含的代码.在您的示例中,它们被执行,因为辅助构造函数使用`:this(0)`语法委托给主构造函数.如果辅助构造函数未委托给主构造函数,则在使用该构造函数初始化类时,不会执行`init`块. (20认同)
  • @yole您的评论使我感到困惑。什么不完全正确?您是说init块不是一直在构造函数之前执行? (2认同)

vod*_*dan 5

简单地说:当创建一个类的实例时,(几乎)首先运行父类的构造函数(如果存在),然后运行主构造函数.

主构造函数从顶部到底部执行在类体中声明的代码.这些名称也可以通过相同的规则获得:

class Foo(a: String = "might be first"
          val b: String = "second" + a) : Boo(a + b + "third"){
    var c = a + "fourth" + b

    init {print("fifth: $c")}

    val d = "sixth"
    init {print("seventh: the end of the primary constructor"}
}
Run Code Online (Sandbox Code Playgroud)

如果您调用辅助构造函数,那么它在主要构造函数之后工作,因为它在链中组成(类似于调用父构造函数).