Reputation: 2024
I have a class that looks something like the following. On line 7, I would like to invoke the init
block directly, however this does not seem to be possible without using reflection.
object MyClass {
var editor: Editor = getDefaultEditor()
set(value) {
field = value
//Todo: figure out how to avoid duplicating init block
project = editor.project!!
document = editor.document.charsSequence.toString().toLowerCase()
findModel = FindManager.getInstance(project).findInFileModel.clone()
findManager = FindManager.getInstance(project)
}
var project: Project
var document: String
var findModel: FindModel
var findManager: FindManager
init {
project = editor.project!!
document = editor.document.charsSequence.toString().toLowerCase()
findModel = FindManager.getInstance(project).findInFileModel.clone()
findManager = FindManager.getInstance(project)
}
}
But I need to have the init
block in order to initialize the properties without instantiating, so if I replace the code inside the init
block with setEditor(getDefaultEditor())
, then the compiler will complain that, "Property must be initialized or be abstract". How do I avoid duplicating all the stuff inside init
?
Upvotes: 1
Views: 1704
Reputation: 8191
I do not know if it is possible to explicitly call the init block.
But I think this should do it for you:
object MyClass {
var editor: Editor = getDefaultEditor()
set(value) {
field = value
init()
}
lateinit var project: Project
lateinit var document: String
lateinit findModel: FindModel
lateinit var findManager: FindManager
init {
init()
}
private fun init() {
project = editor.project!!
document = editor.document.charsSequence.toString().toLowerCase()
findModel = FindManager.getInstance(project).findInFileModel.clone()
findManager = FindManager.getInstance(project)
}
}
But a better design would simply be this:
object MyClass {
var editor: Editor = getDefaultEditor()
fun getProject() = editor.project!!
fun getDocument() = editor.document.charsSequence.toString().toLowerCase()
fun getFindModel() = FindManager.getInstance(getProject()).findInFileModel.clone()
fun getFindManager() = FindManager.getInstance(getProject())
}
Upvotes: 0
Reputation: 24991
You can use lateinit
to say to the compiler "I'll initialize that property later".
lateinit var project: Project
lateinit var document: String
lateinit var findModel: FindModel
lateinit var findManager: FindManager
Then you can omit initialization in init
block and do it whenever you want.
A notice from the official documentation:
The modifier can only be used on var properties declared inside the body of a class (not in the primary constructor), and only when the property does not have a custom getter or setter. The type of the property must be non-null, and it must not be a primitive type.
Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact that it hasn't been initialized.
Upvotes: 3