Lower bound типов или его эмуляция

Предположим, что делается реализация аналога Option/Some/None из Scala. Упрощенная база делается прямолинейно:

sealed class Option<out A> {
    abstract fun isDefined(): Boolean
    abstract fun get(): A
}
class Some<A>(val value: A) : Option<A>() {
    override fun isDefined(): Boolean = true
    override fun get(): A = value
}
object None : Option<Nothing>() {
    override fun isDefined(): Boolean = false
    override fun get(): Nothing = throw NoSuchElementException()
}

Но как добавить getOrElse? Варианты:

  • abstract fun getOrElse(elseBody: () -> A): A - нельзя, поскольку Type parameter A is declared as 'out' but occurs in 'in' position in type () -> A

  • abstract fun <B>getOrElse(elseBody: () -> B): B - можно, для None работает (override fun <B>getOrElse(elseBody: () -> B): B = elseBody()), но для Some нельзя написать override fun <B>getOrElse(elseBody: () -> B): B = value. Очевидно, что value не будет типом B

Как-то необходимо в определении абстрактного getOrElse связать A и B, но не как B : A, а в обратную сторону.

В Scala для этого используется т.н. lower bound: final def getOrElse[B >: A](default: => B): B, но как сделать аналог или эмуляцию lower bound в Kotlin?


Ответы (1 шт):

Автор решения: BccHnw

Напрямую, видимо, не получится. Но вполне рабочий вариант через использование расширения (extension). В прямолинейной реализации:

fun <A> Option<A>.getOrElse(elseBody: () -> A): A {
    return if (this is Some<A>) {
        this.get()
    }
    else {
        elseBody()
    }
}

Работает как нужно.

→ Ссылка