Sealed interface в Kotlin
Ключевое слово Sealed interface задаёт запечатанный контракт
без обязательного общего поля у всех вариантов.
Реализации перечисляют в том же файле, как классы,
реализующие обычный интерфейс; снаружи файла новую
реализацию добавить нельзя, как у sealed class:
sealed interface Row {
data class Text(val value: String) : Row
data class Number(val value: Int) : Row
}
fun main() {
val row: Row = Row.Text("item")
println(row)
}
Интерфейс удобен, когда варианты уже наследуют другой
тип или когда иерархию хотят держать плоской. Функция
может принимать Row и разбирать его в when:
sealed interface Row {
data class Text(val value: String) : Row
data class Number(val value: Int) : Row
}
fun printCell(cell: Row) = when (cell) {
is Row.Text -> cell.value.uppercase()
is Row.Number -> cell.value.toString()
}
fun main() {
println(printCell(Row.Number(42)))
}
В одном файле можно сочетать sealed interface
и sealed class, если нужны разные уровни
иерархии. Для простых наборов вариантов с полями
достаточно одного запечатанного интерфейса и пары
data class:
sealed interface Endpoint {
data class Path(val segments: List<String>) : Endpoint
object Health : Endpoint
}
fun pathOf(e: Endpoint): String = when (e) {
is Endpoint.Path -> e.segments.joinToString("/")
Endpoint.Health -> "health"
}
fun main() {
println(pathOf(Endpoint.Path(listOf("api", "v1"))))
}
Объявите sealed interface Animal:
Dog с полем name: String,
Cat с полем name: String.
Напишите функцию greet(a: Animal): String,
которая для собаки возвращает "woof "
с именем, для кошки - "meow " с именем.
Выведите результат для Animal.Cat("Mila").
Объявите sealed interface Metric:
Counter с полем value: Int,
Gauge с полем level: Double.
Дано:
val m: Metric = Metric.Gauge(0.75)
С помощью when для переменной m
запишите в text строку: для
Counter вида "counter:" и
value, для Gauge - вида
"gauge:" и level (как
"gauge:0.75" в примере).
Выведите text.