Let's take the following code as an example:
val immutableList: List<Any> = listOf<String>()
val mutableList: MutableList<Any> = mutableListOf<String>()
interface SuperList : List<Any>
interface SubList : SuperList, List<String>
As expected, assigning immutableList is allowed, which from my understanding of the docs is because it's marked to say it will only ever return values of T and never take them, so it doesn't matter if it's Any or a subclass.
Also as expected, assigning mutableList gives an error because it cannot offer that guarantee, as casting to MutableList<Any> would let you add an Any to a list of Strings and that would be bad.
I would expect the interface SubList to be fine for the same reason that immutableList is: List's generic functions will only give T, never take it, so returning a String would make both happy. However, its declaration throws the same error as mutableList:
Type parameter E of 'List' has inconsistent values: String, Any
Type parameter E of 'Collection' has inconsistent values: String, Any
Type parameter T of 'Iterable' has inconsistent values: String, Any
Why is this?
Things I've attempted, when trying to understand the cause:
- Having
SubListinherit fromList<Any>directly rather thanSuperList: Gives the same error, so this isn't due to something funky with the layers in the inheritance. - Having
SuperListinherit fromList<out Any>rather thanList<Any>: Gives the errorProjections are not allowed for immediate arguments of a supertype. - Having
SuperListtake a type parameter. This works but like... at that point why doesSuperListeven exist, lol. Much better for my use case to just take an entirely different approach to the goal than to do that.
Context:
My goal was a pair of Table and MutableTable types, and my initial idea was implementing this via extending List<List> and List<MutableList>, respectively. But I wanted to boil the question down to its simplest form, and so chose non-generic classes to use for the sample code.
I have other ideas on how to implement the types, so I'm not looking for an answer to that. I'd just like to understand the root issue that stops this particular approach from working, so that in the future I don't run into other pitfalls with it in ways that might be harder to dodge.