История вопроса:
Интерфейсы с модификатором sealed появились в Kotlin как развитие концепции sealed class. До Kotlin 1.5 только sealed-классы позволяли ограничить набор возможных наследников, что особенно важно для безопасной работы с иерархиями состояний (state machines, DSL, etc). Введя sealed интерфейсы, разработчики предоставили возможность аналогично ограничить реализации интерфейсов, не привязываясь к классам.
Проблема:
Простой открытый интерфейс может быть реализован где угодно в программе, что может привести к неконтролируемому росту числа имплементаций и усложнению поддержки кода. При обработке через when-выражение компилятор не может предупредить о неучтённых ветках.
Решение:
Sealed interface ограничивает реализации только теми, что определены в одном модуле (или том же файле, если interface не является top-level). Это вид контроля применяется для безопасных enum-like структур, паттерна ADT и обработчиков состояния. Компилятор знает все реализации и помогает при анализе кода.
Пример кода:
sealed interface NetworkResult class Success(val data: String): NetworkResult class Error(val cause: Throwable): NetworkResult object Loading: NetworkResult fun handleResult(result: NetworkResult): String = when (result) { is Success -> "Success with ${result.data}" is Error -> "Error: ${result.cause.message}" Loading -> "Loading..." }
Ключевые особенности:
Можно ли реализовать sealed interface вне текущего файла?
Ответ: В отличие от sealed class, sealed интерфейсы могут быть реализованы в других файлах, но только в рамках текущего модуля (или компиляционного юнита, если interface — не top-level).
Могут ли sealed interface иметь открытые методы с реализацией по умолчанию?
Да, как и обычные интерфейсы, sealed интерфейс может содержать default-реализации функций.
sealed interface Mode { fun description(): String = "Unknown mode" }
Возможно ли сериализовать sealed interface с помощью стандартных сериализаторов (например, kotlinx.serialization)?
Возможно, но потребуется явно указать все реализации. В Kotlinx.serialization поддержка sealed интерфейсов появилась не сразу, важно явно указывать сериализуемые типы.
В проекте описали sealed interface для всех типов UI-состояний, а реализации начали появляться в разных частях приложения. Потом добавили новый тип состояния, забыли обновить блок обработки, что привело к игнорированию нового состояния в логах.
Плюсы:
Минусы:
Использовали sealed interface для всех сетевых ответов. Благодаря этому при добавлении нового типа ответа IDE тут же подсветила все места, где обработка коммутируется через when. Ошибка исправляется тут же, нет неожиданных дыр в логике.
Плюсы:
Минусы: