Reputation: 4737
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
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
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