There already several QAs on this question, but for me they seem to talk about different things (Android's Kotlin + Dagger2, in most of the case) and not applying my specific case.
I'm learning Dagger by reading this blog post. Instead using the Java code from that blog, I'm trying to use Kotlin.
So, the House.kt
as interface:
interface House {
fun prepareForWar()
fun reportForWar()
}
The as-is BoltonsDagger.kt
:
class BoltonsDagger @Inject constructor(): House {
override fun reportForWar() {
println("${this.javaClass.simpleName} reporting..")
}
override fun prepareForWar() {
println("${this.javaClass.simpleName} prepared for war")
}
}
The as-is StarksDagger.kt
:
class StarksDagger @Inject constructor(): House {
override fun prepareForWar() {
println("${this.javaClass.simpleName} prepared for war")
}
override fun reportForWar() {
println("${this.javaClass.simpleName} reporting..")
}
}
Finally the WarDagger.kt
with main
function:
class WarDagger @Inject constructor() {
@Inject lateinit var starks: StarksDagger
@Inject lateinit var boltons:BoltonsDagger
fun prepare() {
starks.prepareForWar()
boltons.prepareForWar()
}
fun report() {
starks.reportForWar()
boltons.reportForWar()
}
}
fun main() {
val war = WarDagger()
war.prepare()
war.report()
}
With the error: Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property starks has not been initialized
.
First, change the WarDagger
to following:
class WarDagger @Inject constructor(
private val starks: StarksDagger,
private val boltons: BoltonsDagger
) {
...
}
With this you are making Dagger aware as to how an instance of WarDagger
should be created. There is no need to annotate constructor fields with @Inject
.
I cannot locate dagger component in the question, so let's create one:
@Component
interface WarComponent {
fun provideWarDagger(): WarDagger
}
We are making an instance of WarDagger
accessible through the component, so that clients can get an instance of it.
Now, inside main
instead of manually creating an instance of WarDagger
you should be retrieving it from the dagger component, because that's the whole reason that you are using a DI framework, isn't it? Clients should not be aware how dependencies are being created:
fun main() {
val component = DaggerWarComponent.create()
val war = component.provideWarDagger()
war.prepare()
war.report()
}