Why this is correct and the below one is wrong?
Correct one
fun main () {
AppModule().provideHttpClient(CIO)
}
Wrong
fun <T : HttpClientEngineConfig> provideHttpClient(engineFactory: HttpClientEngineFactory<T> = CIO): HttpClient
Type mismatch.
Required:HttpClientEngineFactory
Found: CIO
With CIO being defined as:
public object CIO : HttpClientEngineFactory<CIOEngineConfig> {
init {
addToLoader()
}
override fun create(block: CIOEngineConfig.() -> Unit): HttpClientEngine =
CIOEngine(CIOEngineConfig().apply(block))
override fun toString(): String = "CIO"
}
CodePudding user response:
The semantics of a generic method is that "I work with any type", so the type parameters of a generic method is specified by the caller - the caller gets to decide what T
is. Therefore, the default value that you specify as the callee must be compatible with HttpClientEngineFactory<T>
, for any T
that the caller might pass in.
Using CIO
doesn't work here, because you are forcing T
to be CIOEngineConfig
.
Imagine what would happen if the default value of CIO
was allowed, and the caller did:
AppModule().provideHttpClient<SomeOtherEngineConfig>()
From the way that provideHttpClient
is declared, this should be possible - I'm passing SomeOtherEngineConfig
for the generic type parameter T
, and since the engineFactory
parameter has a default value, I don't need to pass any other parameters. But when this actually gets run, the default value of CIO
is used for a parameter of type HttpClientEngineFactory<SomeOtherEngineConfig>
!
It's easy to workaround this: simply declare another overload of provideHttpClient
that is not generic:
fun provideHttpClient(): HttpClient = provideHttpClient(CIO)