Samuel Eminet
Samuel Eminet

Reputation: 4737

Kotlin get generic type class using reified

I just started using Kotlin instead of Java and i'm struggling to make refied work to retrieve a generic type class. Here my use case

abstract class BaseDataFragment<VM : BaseViewModel> : BaseFragment()
{
    @Inject
    protected lateinit var viewModelProvider: ViewModelProvider
    protected lateinit var viewModel: VM

    @CallSuper
    override fun init(savedInstanceState: Bundle?)
    {
        viewModel = viewModelProvider.get(getViewModelClass())
    }

    private inline fun <reified T : ViewModel> getViewModelClass():Class<T> = T::class.java
}

Unfortunately i get an error from getViewModelClass():

Cannot use 'VM' as reified type parameter. Use a class instead.

Is there anyway to make it work?

Upvotes: 3

Views: 3359

Answers (2)

Warrior Within
Warrior Within

Reputation: 49

I also struggled with retrieving java class of generic type in Kotlin and finally failed. And I found another way to satisfy this requirement.

abstract class BaseDataFragment: BaseFragment() {
    protected lateinit var viewModel: BaseViewModel
    fun initFragment() {
        viewModel = initVM()
    }
    open fun initVM(): BaseViewModel {
        return viewModelProviders.of(this).get(MyViewModel::java.class)
    }
}

inherited class can override this function to implement owner ViewModel.

Upvotes: 0

yole
yole

Reputation: 97133

reified is not a magical workaround for type erasure. An instance of a generic class on the JVM does not carry any information about the type parameter it was instantiated with. Because the information is not there, reified cannot be used to access it.

reified only works when the type information is known at the call site at compile time, which is not the case here.

If you want to be able to do that, you need to store a Class or KClass as a property of your class, or indeed to create a virtual method for obtaining the Class or KClass instance for each derived class.

Upvotes: 5

Related Questions