Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin class hierarchy and (co)variance

In my setup, I'm trying to have an interface Table that inherits from Map (because it will mostly be used as a wrapper around the map). Two classes inherit from Table - local and global. The global one will have a mutable map, and the local one will have a map of only local entries.

// entries
sealed class Entry {
    class EntryLocal : Entry
    class EntryGlobal : Entry
}

interface Table : Map<String, Entry> {
    fun getRecursive(key: String): Entry?   
}

class GlobalTable(val map:MutableMap<String, Entry>) : Table, Map<String, Entry> by map {
    override fun getRecursive(key: String) = this[key]

    ...
}

class LocalTable(
    private val parent: Table,
    val map: Map<String, EntryLocal>
) : Table, Map<String, EntryLocal> { // gives error
    override fun getRecursive(key: String): Entry? = map[key] ?: parent.getRecursive(key)

}

I get the following error:

Type parameter V of 'Map' has inconsistent values: Entry, EntryVar

Why is that? Doesn't Map<String, EntryLocal> inherit from Map<String, Entry>?

like image 335
Luka Govedič Avatar asked Oct 11 '25 15:10

Luka Govedič


1 Answers

You're right the value type of Map is covariant and so a Map<String, EntryLocal> is a Map<String, Entry>.

However, that's not your problem here. The problem is that LocalTable inherits from both Map<String, EntryLocal> (directly) and Map<String, Entry> (via Table) so it's not clear what the value type should be in LocalTable.

In other words, what's the return type of LocalTable.get? Is it Entry or EntryLocal?

Here's the problem in a nutshell:

interface M<T> {}
interface A : M<String> {}
interface B : M<Object> {}
class C : A, B {}

You'll get the same error saying that parameter T of M has inconsistent values. Even though String is an Object, Kotlin won't assume that the type parameter T of the base class M should therefore be String (or Object).

like image 115
Willis Blackburn Avatar answered Oct 16 '25 11:10

Willis Blackburn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!