Class 什么是Kotlin类初始化语义?

Class 什么是Kotlin类初始化语义?,class,constructor,initialization,kotlin,Class,Constructor,Initialization,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() {

我在语言定义中找不到任何解释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
}
import java.util.Properties
趣味主线(args:Array){
val out=MyClass()
out.fn()
}
类MyClass{
private val a=Properties()//1
初始化{
fn()
}
公众娱乐fn(){
println(“Fn调用.a=$a”)
}
//private val a=Properties()//2
}
运行此程序的结果将根据属性是在(1)还是在(2)处初始化而变化

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

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

嗯,
init
块不是一个。它是一个不同的构造,允许您执行对象的初始化,并且它们[init blocks]是按照属性初始值设定项的声明顺序执行的

构造函数是另一个beast ant,它们是在初始化所有属性并执行所有init块之后执行的。请看以下示例:

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

    init {
        println("Init block")
    }
}

fun main(args: Array<String>) {
    val a = A()
}

您可以将
init
块放在任何需要的地方:在
构造函数之前或之后;它总是在
A
的构造函数(本例中为二级构造函数)之前执行。

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

主构造函数自上而下执行类主体中声明的代码。同样,名称也可以通过相同的规则使用:

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"}
}

如果调用次要构造函数,则它在主构造函数之后工作,因为它在链中构成(类似于调用父构造函数)。

这并不完全正确<代码>初始化
块包含包含在主构造函数中的代码。在您的示例中,执行它们是因为辅助构造函数使用
:this(0)
语法委托给主构造函数。如果二级构造函数没有委托给主构造函数,
init
块将不会在使用该构造函数初始化类时执行。您好,Aga/Yole-感谢您的回答。我可能应该说我是Kotlin n00b,但我的问题很清楚。我认为你的两个回答都来自于对语言的熟悉。当我阅读Kotlin的定义时,我发现对init的唯一引用是:“主构造函数不能包含任何代码。初始化代码可以放在初始值设定项块中,初始值设定项块的前缀是init关键字”。但是,没有说明初始化的顺序。(我可以看到)@aga你可以根据反馈编辑你的答案,这样新读者就可以清楚地看到,而不必扫描评论。编辑就是为了这个原因,总是根据持续的反馈创建清晰的答案。当你的答案更清楚时,我会投赞成票。您可能希望从示例中排除辅助构造函数,然后添加关于它的附加说明。它们并不太常见,也混淆了你答案的要点。@yole我知道你的答案有点陈旧,但我希望你能为我澄清一些事情。您提到“如果辅助构造函数没有委托给主构造函数…”-在什么情况下会发生这种情况?Kotlin文档中写道:“如果类有一个主构造函数,那么每个次构造函数都需要直接或间接地通过另一个次构造函数委托给主构造函数。”“情况并非总是这样吗?@yole你的评论让我感到困惑。什么是不完全正确的?你的意思是init block不总是在构造函数之前执行吗?你能在确定顺序后重写它吗?并且可以删除“几乎”和“可能是”,以便它是一个决定性的答案。或者听从@aga的回答
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"}
}