classkotlinretrofit2

kotlin, how to return class type from a function


having a base class A, and the class B and C both extend from A

in A it has function to create a retrofit service, which takes a class type as pram:

protected fun <T> createRemoteService(clazz: Class<T>, baseUrl: String): T {
    return Retrofit.Builder()
        .baseUrl(baseUrl)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create(createGson()))
        .build()
        .create(clazz)
}

and in class B and C, the service could be created as (with IBService::class.java or ICService::class.java passed in respectively):

in B:

var remoteServ: IBService
init {
    remoteApi = createRemoteService(IBService::class.java, getBaseUrl())
}

and in C:

var remoteServ: ICService
init {
    remoteApi = createRemoteService(ICService::class.java, getBaseUrl())
}

it is ok to pass IBService::class.java as the Class<T>

would like to have a abstract function in base A to return the class type

abstract fun<T> getRemoteServiceClassType() : Class<T>

so it could be done in base A to create the service by getting the class type

remoteServ: Any = createRemoteApi(getRemoteServiceClassType(), getBaseUrl())

and implementation in class B (got error):

override fun<T> getRemoteServiceClassType() : Class<T> {
    return IBService::class.java  //<=== got compiler error “Type inference 
                                  // failed. Expected type mismatch: required Class<T>
                                  // found Class<IBService>
}

interface IBService {
    @GET
    fun getRemoteData(@Url url: String,
                  @HeaderMap headers: Map<String, String>,
                  @QueryMap params: Map<String, String>?): 
        Call<BResponseData>

}

why cant return IBService::java.class for the Class<T>, but passing IBService::class.java to a function where requires a Class<T> is ok?


Solution

  • The "correct" signature for getRemoteServiceClassType is

    abstract fun getRemoteServiceClassType() : Class<*>
    

    if any class at all can be returned, or

    abstract fun getRemoteServiceClassType() : Class<out SuperType>
    

    if all services should have a common supertype. See https://kotlinlang.org/docs/reference/generics.html for explanation.