Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 645
lannyf Avatar asked Jun 11 '18 18:06

lannyf


People also ask

Can a method return type be a class?

When a method uses a class name as its return type, such as pop does, the class of the type of the returned object must be either a subclass of or the exact class of the return type.

What is () -> unit in Kotlin?

Unit in Kotlin corresponds to the void in Java. Like void, Unit is the return type of any function that does not return any meaningful value, and it is optional to mention the Unit as the return type. But unlike void, Unit is a real class (Singleton) with only one instance.

What is the default return type of a function in Kotlin?

By default, Java void is mapped to Unit type in Kotlin. This means that any method that returns void in Java when called from Kotlin will return Unit — for example the System. out. println() function.


1 Answers

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.

like image 182
Alexey Romanov Avatar answered Sep 24 '22 08:09

Alexey Romanov