Android Kotlin: How do I create an instance of the inherited type using Generics?

Here's a simplified code of what I am doing:

I have this custom ViewHolder:

open class AsyncViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    ....
}

I inherit from above ViewHolder and later on need to create a AsyncCellAdapter of the inherited type. I am doing this using Generics:

abstract class AsyncCellAdapter<T: AsyncCellAdapter.AsyncViewHolder>() : RecyclerView.Adapter<T>(){
    ....

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): T {
        val viewHolder = T(View(parent.context)) //<----------Here's the problem
        ....
        return viewHolder
    }

    ....
}

The problem arises at the T in the line T(View(parent.context))

It gives me error:

Type parameter T cannot be called as function

How do I create an instance of the inherited type using Generics and return that?

Upvotes: 1

Views: 302

Answers (1)

Tenfour04
Tenfour04

Reputation: 93609

Due to type erasure, you cannot do this without passing the concrete class to the constructor. Or, to avoid having to use reflection to find and call the constructor, it would be cleaner to give the constructor a function parameter for constructing the ViewHolder, so you can just pass the a constructor reference.

Example:

abstract class AsyncCellAdapter<T: AsyncCellAdapter.AsyncViewHolder>(
    private val viewHolderConstructor: (View)->T
): RecyclerView.Adapter<T>(){
    //...

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): T {
        val viewHolder = viewHolderConstructor(View(parent.context)) 
        //...
        return viewHolder
    }

    //...
}

// Example subclass:
class MyAdapter: AsyncCellAdapter<MyAdapter.MyViewHolder>(::MyViewHolder) {

    class MyViewHolder(itemView: View): AsyncCellAdapter.AsyncViewHolder(itemView)

}

Upvotes: 5

Related Questions