I can't seem to wrap my head around Kotlin generics, please help
I read here and here and I still can't determine how to make this work. I have a RecyclerView adapter that uses an abstracted parent BaseFieldVH as the ViewHolder class.
So the Adapter class looks like this:
class MyAdapter() : RecyclerView.Adapter<BaseFieldVH<*>>() {
...
override fun onBindViewHolder(holder: BaseFieldVH<*>, position: Int) {
holder.bind(data[position])
}
}
And the ViewHolder implementation looks like this:
abstract class BaseFieldVH<in FF : BaseFormField>
(itemView: View) : RecyclerView.ViewHolder(itemView) {
...
abstract fun bind(formField: FF)
}
But the actual call to holder.bind(data[position])
is displaying the error:
Out-projected type 'BaseFieldVH<*>' prohibits the use of 'public
abstract fun bind(formField: FF): Unit defined in ...
use in Nothing?
I've also tried defining the Adapter with BaseFieldVH<in Nothing>
but then I get a Type Mismatch error for attempting to put Nothing into a function that requires a BaseFormField.
use BaseFormField
Defining the Adapter with BaseFieldVH<iBaseFormField>
actually resolves the binding issue, but then in the onCreateViewHolder there is a type mismatch for the view holders:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseFieldVH<BaseFormField> {
val itemView: View
when (viewType) {
HEADER_TYPE -> {
itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_header, parent, false)
return HeaderVH(itemView)
}
HeaderVH is an extension of BaseFieldVH, and so there's a type mismatch
It looks like the answer to this issue is that you can't implement a ViewHolder class that specifies a generic for binding. My guess is this arises from the fact that the RecyclerView.Adapter is written in Java and any Kotlin extension is too restrictive to implement it properly.
If you can contradict this conclusion, let me know!
I found this post which explains the whole projection concept in a way that I could understand.
In the end I abandoned my attempt to control the Type for the ViewHolder:
This means each child class of BaseFieldVH has to do some a type check in its bind function. For instance:
}
But now at least I'm not getting any errors.