Kotlin 在构造函数中初始化变量内部函数

Kotlin Initialize Variable Inside Function in Constructor

在 Kotlin 中,未声明为 nullable 或 lateinit 的变量必须在构造函数(或 init)中初始化。我正在尝试这样做:

class Foo{
    var foo:myType
    init{
        complicatedFooInit()
    }

    fun complicatedFooInit(){
         foo = //a whole bunch of code here
    }

}

我仍然收到 Property must be initialized or declared abstract 错误。您可以通过使 myType 成为 Int 并在 complicatedFooInit 函数中将其设置为等于 3 来轻松重现这一点。显然有很多方法可以解决这个问题(只是不让它成为一个函数,让 complicatedFooInit return myType 和设置 foo 等于它,等等)。我的问题是,为什么上面的代码无效?或者经过一些调整是否有效?

编译器不知道 complicatedFooInit() 函数内部发生了什么(因为调查从 init 块调用的潜在数十个嵌套函数的所有执行流程可能负担过重)。他想直接在 init 块中查看初始化。所以你需要使 complicatedFooInit() return 期望值:

class Foo {
    var foo: myType

    init {
        foo = complicatedFooInit()
    }

    fun complicatedFooInit(): myType {
        //a whole bunch of code here
       return ...
    }
}

实际上,在这种情况下 属性 在声明站点初始化会更简洁(根本不需要 init 块):

var foo: String = complicatedFooInit()

还要考虑你可以有多个 init 块,所以如果你想将初始化的某些部分提取到一个函数中,例如

init {
    complicatedFooInit()
    complicatedBarInit()
}

我会用单独的 init 块替换每个函数:

// comment about foo initialization
init {
    // body of complicatedFooInit()
}

// comment about bar initialization
init {
    // body of complicatedBarInit()
}

问题是您不能将参数传递给 init 块;但是您传递给 complicatedFooInit 的任何参数只能取决于主构造函数参数,因此可以在相应的 init 块的开头设置。

你也不能用不同的参数调用同一个函数两次,

init {
    complicatedFooInit(true)
    complicatedFooInit(false)
}

但无论如何你都不想这样做,因为它会初始化 foo 两次; unless complicatedFooInit 根据其参数初始化不同的变量,但这会使 Михаил Нафталь 的回答中提到的编译器负担更糟!