Suppose I have a heterogeneous map container, where keys contain type information on values:
interface Container<K : Container.Key<*>> {
interface Key<V>
interface Entry<K : Key<V>, V>
}
I want to have a get() function akin to
fun <V> get(key: Key<V>): V?
but also restrict this function to our type parameter K - The idea is that a class that implements Container might also have their custom key type Container.Key<V>, and we want the input parameter to get() be Container.Key<V> as a result.
Is this expressible in Kotlin?
No, this is not possible (yet).
You essentially want:
That is,
getshould take a thing that is both aK, and aKey<V>. Unfortunately, this kind of intersection type is not available yet.Kotlin only supports intersection types of the form
T & Any, whereTis a nullable type parameter, to express "the non-nullable version of T".There is a lengthy discussion here about adding better intersection type support.
So for now, you can only enforce
TKey: K & Key<V>at runtime. Take in two parameters - aKand aKey<V>. Enforce that they are the same object.In the implementation you should check
key1 === key2.Note that we cannot check that a key is indeed a
Key<V>and notKey<SomethingElse>at runtime, becauseVis erased. You can take aKClass<V>to work around this, but that doesn't work well ifVis itself parameterised.If that is fine for you, and your
Keyinterface has a way to tell you if it is aKey<V>, given aKClass<V>, you can use a signature like this instead: