简体   繁体   English

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

[英]Kotlin Initialize Variable Inside Function in Constructor

In Kotlin variables not declared as nullable or lateinit must be initialized in the constructor (or init).在 Kotlin 中,未声明为 nullable 或 lateinit 的变量必须在构造函数(或 init)中初始化。 I am trying to do this like this:我正在尝试这样做:

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

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

}

I still get the Property must be initialized or declared abstract error.我仍然得到Property must be initialized or declared abstract错误。 You can easily reproduce this by making myType an Int and just setting it equal to 3 in the complicatedFooInit function.您可以通过将myType设置为Int并在complicatedFooInit function 中将其设置为 3 来轻松重现这一点。 Obviously there are ways around this (just not making it a function, having complicatedFooInit return myType and setting foo equal to it, etc.).显然有办法解决这个问题(只是不让它成为 function,让complicatedFooInit返回myType并将 foo 设置为等于它,等等)。 My question is, why is the above code invalid?我的问题是,为什么上面的代码无效? Or is it valid with some tweaking?或者通过一些调整是否有效?

Compiler have no idea what's going on inside complicatedFooInit() function (cause it may be too burden to investigate all execution flow of potentially dozens nested functions called from init block).编译器不知道 complexFooInit( complicatedFooInit() function 内部发生了什么(因为调查从init块调用的可能数十个嵌套函数的所有执行流程可能负担过重)。 He wants to see initialization directly inside init block.他想直接在init块中查看初始化。 So you need to make complicatedFooInit() return desired value:所以你需要让complicatedFooInit()返回所需的值:

class Foo {
    var foo: myType

    init {
        foo = complicatedFooInit()
    }

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

Actually, in this case property initialization on declaration site will be more concise (no need for init block at all):实际上,在这种情况下,声明站点上的属性初始化会更简洁(根本不需要init块):

var foo: String = complicatedFooInit()

Consider also that you can have multiple init blocks, so if you want to extract some part of initialization into a function, eg还要考虑你可以有多个init块,所以如果你想将初始化的某些部分提取到 function 中,例如

init {
    complicatedFooInit()
    complicatedBarInit()
}

I would replace each function by a separate init block:我会用一个单独的init块替换每个 function :

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

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

The problem is that you can't pass arguments to init blocks;问题是您不能将 arguments 传递给init块; but any arguments you'd pass to complicatedFooInit can only depend on the primary constructor parameters, and so can be set up in the beginning of the corresponding init block.但是您传递给complicatedFooInit的任何 arguments 只能依赖于主构造函数参数,因此可以在相应init块的开头进行设置。

You also can't call the same function twice with different parameters,您也不能使用不同的参数两次调用相同的 function,

init {
    complicatedFooInit(true)
    complicatedFooInit(false)
}

but you wouldn't want to anyway, because it would initialize foo twice;但无论如何你都不想这样做,因为它会初始化foo两次; unless complicatedFooInit initializes different variables depending on its arguments, but it would make the compiler's burden mentioned in Михаил Нафталь's answer much worse!除非complicatedFooInit根据其 arguments 初始化不同的变量,但这会使Михаил Нафталь 的答案中提到的编译器负担更糟!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM