https://kotlinlang.org logo
#android
Title
# android
m

matt_dziubek

07/24/2017, 8:27 AM
Hi guys, I’ve got a problem with Kotlin, which involves generics. Stick with me though 😉. I have a below generic interface:
Copy code
interface RecyclerItem<in T : RecyclerView.ViewHolder> {

    fun onBindViewHolder(holder: T?)
}
Generic is defined as
in
because clearly
RecyclerItem
is a consumer, hence I can only assign this instance to its subtype. I also have a below implementations of `RecyclerItem`:
Copy code
class ItemSuncalcData() : RecyclerItem<ItemSuncalcData.ViewHolder>
and:
Copy code
class SomeOtherItem() : RecyclerItem<SomeOtherItem.ViewHolder>
Long story short I want to store above two instances in a
List<RecyclerItem<RecyclerView.ViewHolder>>
, but because of
in T
I can’t assign subclasses to its supertypes. What’s my best move here? I’ve written same code in java and only got unchecked cast warning. The only way I could think of was to remove generics from the interface:
Copy code
interface RecyclerItem {

    fun onBindViewHolder(holder: RecyclerView.ViewHolder?)
}
But before I’ll change 15+ files (because of casting I would have to make) I wanted to ask you first, thanks in advance 😉 Take a look at this github repo I made showcasing my problem above: https://github.com/matdziu/GenericsKotlin. You can switch between two commits - one that uses generic way (compilation error in MainActivity) and the second which is the solution I think I found. Note that on production we’re using multiple different item types and factory pattern to choose a proper view holder (this sample is just a huge simplification).
m

mzgreen

07/24/2017, 8:35 AM
Have you tried
List<RecyclerItem<*>>
?
m

matt_dziubek

07/24/2017, 8:50 AM
yes, didn’t work
could you look at my sample and confirm?
m

mzgreen

07/24/2017, 9:13 AM
Copy code
class RecyclerView{
    interface ViewHolder
}

interface RecyclerItem<in T : RecyclerView.ViewHolder> {
     fun onBindViewHolder(holder: T?)
} 

class ItemTextView : RecyclerItem<ItemTextView.ViewHolder> {

    override fun onBindViewHolder(holder: ViewHolder?) {}

    class ViewHolder : RecyclerView.ViewHolder {}
}

fun main(args: Array<String>) {
	
    val list = mutableListOf<RecyclerItem<*>>()
    list.add(ItemTextView())
    
    println(list.size) // prints 1
}
2 Views