I notice that classes in Kotlin can have more than one init block. If so, they are executed in sequence.
What is a good use case for having more than one?
Kotlin init The init block is run every time the class is instantiated, with any kind of constructor as we shall see next. Multiple initializer blocks can be written in a class.
Moreover, we also have a secondary constructor that only accepts the person's last name. In addition to these two constructors, we're declaring two variables with property initializers based on the constructor inputs. Finally, we have two initializer blocks (blocks prefixed with the keyword init).
Kotlin init is one of the blocks and it is used to execute the class is instantiated and the init block is run at every time the class is instantiated with any kind of constructors for to create the objects and called at the main method or wherever it requires the multiple initializer blocks also written with the ...
Code in initializer blocks effectively becomes part of the primary constructor. Delegation to the primary constructor happens as the first statement of a secondary constructor, so the code in all initializer blocks and property initializers is executed before the body of the secondary constructor.
Consider the following snippet.
class Foo() {
val x = Bar.getValue()
init {
// check the validity of x and abort if invalid
}
val y = Cow.getValue(x) // requires x to be valid
init {
// continue with initialization
}
}
Since primary constructor cannot have any code, the above situation would not be possible without multiple init blocks. In other words, the ability to have multiple init blocks helps tackle dependencies involving properties during initialization; more so, when properties are read-only.
Update on 10/16/2021: We can achieve the same behavior by moving the assignment of read-only (RO) properties into a single init
block. However, by doing so, we will separate the declaration of a RO property and its initialization. In comparison, multiple init
blocks help keep the declaration and initialization of RO properties together while allowing any dependent computation to follow the property initialization. Consequently, the code is a bit cleaner, easy to read/understand, and modular (as described by @mightyWOZ's reply).
One use case would be to modularize
class
initialization
.
If a class have multiple dependencies and initialization of each dependency is non-trivial, then it makes sense to have an individual init
block for each dependency initialization, so that your code remains manageable. you can have a single init block but the code would be hard to follow and manage.
I think Single responsibility principle applies here.
For example, let's say we have a class which have multiple dependencies, if you use multiple init blocks, your code would be
// Initialization code for dependency 1
init{
// complex calculations for dependency 1 initialization
}
// Initialization code for dependency 2
init{
// complex calculations for dependency 2 initialization
}
// Initialization code for dependency n
init{
// complex calculations for nth dependency initialization
}
Here your initialization looks clear, and you can see which init block does what.
If however, you use a single init block, your code would be
// Initialization code for all dependencies
init{
// complex calculations for 1st dependency initialization
// complex calculations for 2nd dependency initialization
// complex calculations for nth dependency initialization
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With