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

1

11

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?

Shala answered 15/2, 2018 at 16:18 Comment(4)
Is that type parameter only relevant in the depicted method? You could make T a reified method type parameter insteadColeorhiza
@Coleorhiza no, T will be relevant in lots of methods. I could make all of the methods take T (no pun intended) rather than the class, but I feel that it's counter productive when T is the same throughout the class. - I'm guessing this is either difficult or impossible due to JVM's compile time type erasure? (I come from C#, where the CLR is fully type aware, even when it comes to GTPs, so this would be trivial)Shala
discuss.kotlinlang.org/t/reified-type-parameters-in-classes/…Coleorhiza
I have a similar problem here Modularising to create a function with variable Types in Kotlin. Can you please help.Detonation
F
18

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.

Fluoresce answered 16/2, 2018 at 6:52 Comment(4)
This is a nice way to provide the desired behaviour although I don’t agree with the constructor-like looking of funs. ++Coleorhiza
@Coleorhiza I am a big fan of Scala's uniform access principle and this is the one case in which Kotlin extends it even further.Fluoresce
@AlexeyRomanov I like this, though I did move the contructor-like function to a companion object and renamed it createRepository.Shala
I have a similar problem here Modularising to create a function with variable Types in Kotlin. Can you please help.Detonation

© 2022 - 2024 — McMap. All rights reserved.