What is the proper way to create new instance of generic class in kotlin?
Thanks to Kirill Rakhman I wrote a similar answer (for Android adapter). A difference here is in a parameter of the class.
private fun <T> createItem(
viewGroup: ViewGroup,
layoutRes: Int,
method: (View) -> T
): T {
val view = LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false)
return method(view) // Creates T(view).
}
Then use it this way:
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AbstractViewHolder {
return when (viewType) {
LOADER -> createItem(viewGroup, R.layout.row_loader, ::LoaderViewHolder)
DATE -> createItem(viewGroup, R.layout.row_date, ::DateViewHolder)
else -> throw IllegalStateException("Wrong class")
}
}
Here LoaderViewHolder
and DateViewHolder
are descendants of AbstractViewHolder
.
If you let IntelliJ add explicit type information, you see that entityClass
is actually of type Class<Class<String>>
. I'm not sure if that's what you want. In line 2 you are first creating an instance of Class<T>
and then one of T
but that's not possible anyway, because the generic information about T
is lost at runtime. Apart from that you can't instantiate class objects directly.
Solution
One possible solution would be to add a parameter of type Class<T>
to your function or class and use it to instantiate objects like this.
fun <T> foo(entityClass: Class<T>) {
var entity: T = entityClass.newInstance()
}
fun test() {
foo(Object::class.java)
}
But there's actually a more elegant solution without the use of reflection. Define a parameter of method type () -> T
and use constructor references. Here's my related question about constructor references and here's the code:
fun <T> foo2(factory: () -> T) {
var entity: T = factory()
}
fun test() {
foo2(::Object)
}