Reputation: 345
I'm trying to add Example
class into a list of Delegate
through addDelegate
function. Unfortunately, I got an error :
TypeMismatch: Required Delegate<Item, CoreHolder> found Example
Here's my code (It's not full code, it just some piece of code that relevant to my question):
interface Delegate <T, VH: CoreHolder> {
fun onCreate(parent: ViewGroup): VH
fun onBind(items: List<T>, holder: VH)
}
class DelegateManager<T, VH: CoreHolder> {
private val delegates = mutableListOf<Delegate<T, VH>>()
fun addDelegate(delegate: Delegate<T, VH>) {
delegates.add(delegate)
}
}
class GenericDelegateManager<T> {
private val delegateManager = DelegateManager<T, CoreHolder> = DelegateManager()
fun addDelegate(delegate: Delegate<T, CoreHolder>) {
delegateManager.addDelegate(adapterDelegate)
}
}
class Main {
val genericDelegateManager = GenericDelegateManager<Item>()
fun main() {
genericDelegateManager.addDelegate(Example())
genericDelegateManager.addDelegate(Example2())
}
}
class Example: Delegate<Item, Example.ViewHolder> {
class ViewHolder: CoreHolder {
//...
}
}
class Example2: Delegate<Item, Example2.ViewHolder> {
class ViewHolder: CoreHolder {
//...
}
}
Current workarounds : I've found 2 workarounds but I think it's not the best way for doing it,
addDelegate
function's parameter to Delegate<T, out CoreHolder>
and cast it to Delegate<T, CoreHolder>
but I got a warning "Unchecked Cast". So the code become @SurpressWarning("UNCHECKED_CAST")
fun addDelegate(delegate: Delegate<T, out CoreHolder>) {
delegates.add(delegate as Delegate<T, CoreHolder>)
}
Delegate
interface type parameter to <T, out VH>
and change onBind
to fun onBind(items: List<T>, holder: @UnsafeVariance VH)
so the code become interface Delegate <T, out VH: CoreHolder> {
fun onBind(items: List<T>, holder: @UnsafeVariance VH)
}
All those two solutions work, can run and behave as expected. But the code isn’t that fancy.
Is there another better way to solve this kind of problem? Thanks
Upvotes: 1
Views: 155
Reputation: 3689
Short - it is impossible to combine these classes to the one DelegateManager
. The task can be simplified to the following:
fun <TKey> someMethod(pair1: Pair1<TKey>, pair2: Pair2<TKey>) {
val map = mutableMapOf<TKey, ???>()
map[pair1.key] = pair1.value
map[pair2.key] = pair2.value
}
class Pair1<TKey>(val key: TKey, val value: String)
class Pair2<TKey>(val key: TKey, val value: Int)
As you can see, you couldn't replace ???
to anything, which provides compilable code.
However example can be reworked to:
fun <TKey> someMethod(pair1: Pair<TKey, CiImpl1>, pair2: Pair<TKey, CiImpl2>) {
val map = mutableMapOf<TKey, CommonInterface>()
map[pair1.key] = pair1.value
map[pair2.key] = pair2.value
}
class Pair<TKey, TValue: CommonInterface>(val key: TKey, val value: TValue)
class CiImpl1: CommonInterface
class CiImpl2: CommonInterface
interface CommonInterface
Finally: you couldn't put Example
and Example2
classes into the common collection, the same with my code. Moreover, you couldn't just use Delegate<?, CoreHolder>
, because it accepts any implementation of CoreHolder
, which is not acceptable for you.
Upvotes: 1