I have some Drawers with generics:
abstract class BaseGeoDrawer<KEY : Any, GEO : Any, ITEM : Any>
abstract class BasePolygonDrawer<KEY : Any, ITEM : Any>: BaseGeoDrawer<KEY, Polygon, ITEM>
class TeamAreaDrawer : BasePolygonDrawer<String, Team>
abstract class BaseMarkerDrawer<KEY : Any, ITEM : Any> : BaseGeoDrawer<KEY, Marker, ITEM>
class TeamPositionDrawer : BaseMarkerDrawer<String, Team>
Then I have a controller that accept these Drawers, putting them in a ArrayList
private val drawers = ArrayList<BaseGeoDrawer<Any, Any, Any>>()
open fun addGeoDrawer(drawer: BaseGeoDrawer<Any, Any, Any>) {
drawers.add(drawer)
}
And later on calling methods in these Drawers
//Method in controller
private fun onMarkerClicked(marker: Marker): Boolean {
return drawers.any { it.onGeoClicked(marker) }
}
//Method in BaseGeoDrawer
fun onGeoClicked(geo: GEO): Boolean
The problem appear on this line
teamAreaDrawer = TeamAreaDrawer(this)
mapController.addGeoDrawer(teamAreaDrawer)
Android Studio will not allow it, telling me
Type mismatch.
Required: BaseGeoDrawer<Any, Any, Any>
Found: TeamAreaDrawer
I tried using out for drawers
private val drawers = ArrayList<BaseGeoDrawer<out Any, out Any, out Any>>()
But then onMarkerClicked will not compile, with the following error
Out-projected type BaseGeoDrawer<out Any, out Any, out Any> prohibits the use of 'public final fun onGeoClicked(geo: GEO) defined in mypackage.BaseGeoDrawer'
The problem here is that you need
GEOas a contravariant type parameter inBaseGeoDrawerto useonGeoClicked(GEO)butArrayList<BaseGeoDrawer<Any, Any, Any>>is invariant in its type. This means that you can't add anything else than aBaseGeoDrawer<Any, Any, Any>. If you try to use the types ofBaseGeoDraweras covariant it will not compile because you need it as contravariant when you callonGeoClicked(GEO).Considering that until now in Kotlin a type parameter can't be bivariant, the only way to do it, is to do an unchecked cast.
In this specific case, you can do:
If you think about it, in Java, you would have done the same, because you would have had:
I recommend you to read more about variance here.