Reputation: 154
In Kotlin variables not declared as nullable or lateinit must be initialized in the constructor (or 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. You can easily reproduce this by making myType
an Int
and just setting it equal to 3 in the complicatedFooInit
function. Obviously there are ways around this (just not making it a function, having complicatedFooInit
return myType
and setting foo equal to it, etc.). My question is, why is the above code invalid? Or is it valid with some tweaking?
Upvotes: 0
Views: 3254
Reputation: 170723
Consider also that you can have multiple init
blocks, so if you want to extract some part of initialization into a function, e.g.
init {
complicatedFooInit()
complicatedBarInit()
}
I would replace each function by a separate init
block:
// 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; 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.
You also can't call the same function twice with different parameters,
init {
complicatedFooInit(true)
complicatedFooInit(false)
}
but you wouldn't want to anyway, because it would initialize foo
twice; unless complicatedFooInit
initializes different variables depending on its arguments, but it would make the compiler's burden mentioned in Михаил Нафталь's answer much worse!
Upvotes: 2
Reputation: 7882
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). He wants to see initialization directly inside init
block. So you need to make complicatedFooInit()
return desired value:
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):
var foo: String = complicatedFooInit()
Upvotes: 5