I want to define an Option type, and then pseudo-polymorphically define a getOrNull
operation.
sealed interface Option<out T>
data class Some<out T>(val value: T): Option<T>
object None: Option<Nothing>
fun <T> Option<T>.getOrNull(): T? = when (this) {
is Some<T> -> getOrNull()
is None -> getOrNull()
}
fun <T> Some<T>.getOrNull(): T = value
fun None.getOrNull(): Nothing? = null
This all works fine.
But if I tighten the generic type to disallow Option(null)
by specifying T: Any
fun <T: Any> Option<T>.getOrNull(): T? = when (this) {
is Some<T> -> getOrNull()
is None -> getOrNull()
}
then I get
Kotlin: Overload resolution ambiguity:
public fun <T : Any> Option<TypeVariable(T)>.getOrNull(): TypeVariable(T)? defined in root package in file Delme.kt
public fun <T> Some<TypeVariable(T)>.getOrNull(): TypeVariable(T) defined in root package in file Delme.kt
for the line is Some<T> -> getOrNull()
How can I tell the compiler which of the two subclass extension functions it should be calling?
CodePudding user response:
The thing is, when you constrain the T of Option<T>.getOrNull
but NOT the T
of Some<T>.getOrNull
you take away the fact that one was more specific than the other (a subtype). Now, they are just "different", hence the resolution ambiguity (the compiler cannot "order" them by specificity anymore).
You can solve it by also constraining Some<T>.getOrNull
with Any
:
fun <T : Any> Some<T>.getOrNull(): T = value