Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin - get T::class.java from class generic type parameter

Tags:

kotlin

corda

I'm trying to build a generic repository around Corda's vault. It should look something like this:

class VaultRepository<out T : ContractState>(private val services: CordaRPCOps) {

    fun getUnconsumedStateByExternalId(externalId: String): T {
        return services.vaultQuery<T>(...).states.single().state.data
    }
}

But I get this error:

Cannot use 'T' as reified type parameter

I could use another vaultQuery function, which takes a Class<T> instead as a parameter, but I need to be able to get it from VaultRepository<T> first.

Is there a way to get T from a classes generic type parameter list?

like image 536
Matthew Layton Avatar asked Feb 15 '18 16:02

Matthew Layton


People also ask

How do you get a class from generic type Kotlin?

There are no direct ways to do this in Kotlin. In order to check the generic type, we need to create an instance of the generic class<T> and then we can compare the same with our class.

What does :: class Java do Kotlin?

By using ::class , you get an instance of KClass. It is Kotlin Reflection API, that can handle Kotlin features like properties, data classes, etc. By using ::class. java , you get an instance of Class.

How do you find the class object of a generic type?

Pass the class object instead and it's easy. The idea here is that since you can't extract the type parameter from the object, you have to do it the other way around: start with the class and then manipulate the object to match the type parameter.

What does :: class mean in Kotlin?

:: is just a way to write a lambda expression basically we can use this to refer to a method i.e a member function or property for example class Person (val name: String, val age: Int) Now we can write this to access the person which has the maximium age.


1 Answers

My go-to solution is to add a Class<T> parameter to the primary constructor and a constructor-like function which gets the Class from reified T.

class VaultRepository<out T : ContractState>(
    private val services: CordaRPCOps,
    private val clazz: Class<T>
) {
    fun getUnconsumedStateByExternalId(externalId: String): T {
        return services.vaultQuery(..., clazz).states.single().state.data
    }
}

fun VaultRepository<reified T : ContractState>(services: CordaRPCOps) =
    VaultRepository(services, T::class.java)

To anticipate a specific comment: some people think funs shouldn't look like constructors. The Kotlin team doesn't agree.

like image 135
Alexey Romanov Avatar answered Oct 08 '22 05:10

Alexey Romanov