← Назад к вопросам

В чем разница между sealed class и абстрактным классом?

2.3 Middle🔥 253 комментариев
#Kotlin основы#Архитектура и паттерны

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные отличия sealed class от abstract class

Sealed class (запечатанный класс) и abstract class (абстрактный класс) в Kotlin — это два разных инструмента для организации иерархий классов, но они решают разные задачи и имеют различные ограничения.

1. Ключевая цель и семантика

Абстрактный класс — это механизм наследования и полиморфизма, который:

  • Предоставляет частичную реализацию
  • Определяет абстрактные методы, которые должны быть реализованы в наследниках
  • Используется для вынесения общего поведения и создания базовой функциональности
  • Позволяет создавать открытые иерархии (можно наследоваться где угодно)
abstract class Vehicle {
    abstract fun move()
    fun honk() = println("Beep!")
}

class Car : Vehicle() {
    override fun move() = println("Driving")
}

// Можно продолжить иерархию в другом файле или модуле

Sealed class — это механизм ограниченных иерархий:

  • Определяет закрытое множество наследников
  • Все подклассы должны быть объявлены в том же файле (до Kotlin 1.5) или в том же модуле/пакете (с Kotlin 1.5+)
  • Используется для представления ограниченного набора вариантов (как enum, но с состоянием)
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

// Все наследники определены — иерархия закрыта

2. Ограничения наследования

Абстрактный класс:

  • Можно наследоваться из любого места (если класс не помечен как final)
  • Количество наследников не ограничено
  • Наследники могут быть в разных файлах и модулях

Sealed class:

  • Набор наследников фиксирован и известен на этапе компиляции
  • Все наследники должны быть объявлены в той же области видимости
  • Компилятор знает все возможные варианты, что позволяет делать исчерпывающие when-выражения
fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println("Data: ${result.data}")
        is Result.Error -> println("Error: ${result.message}")
        Result.Loading -> println("Loading...")
        // Компилятор знает, что все случаи покрыты — else не нужен!
    }
}

3. Практическое применение

Абстрактный класс используем, когда:

  • Нужна общая реализация для группы классов
  • Требуется частичная реализация с шаблонным методом
  • Создаем базовый класс для плагинов или расширяемой архитектуры
  • Хотим предоставить дефолтное поведение

Sealed class идеально подходит для:

  • Представления состояний (загрузка, успех, ошибка)
  • Реализации алгебраических типов данных (ADT)
  • Обработки команд или событий в конечных автоматах
  • Создания DSL или ограниченных наборов операций

4. Технические различия

ХарактеристикаAbstract classSealed class
Модификатор доступаМожет быть open, abstractВсегда open для наследников
КонструкторыМогут быть любыеТолько protected или private
НаследникиЛюбые классыТолько классы/объекты из того же файла/пакета
Когда использоватьДля повторного использования кодаДля ограниченного набора вариантов
Исчерпывающая проверкаНетДа (в when-выражениях)

5. Пример комбинированного использования

Иногда эти подходы можно сочетать:

sealed class UIState {
    abstract fun render(): View
    
    object Loading : UIState() {
        override fun render() = LoadingView()
    }
    
    data class Content(val items: List<Item>) : UIState() {
        override fun render() = ListView(items)
    }
    
    data class Error(val exception: Throwable) : UIState() {
        override fun render() = ErrorView(exception.message)
    }
}

Вывод

Абстрактный класс — это инструмент для кодовой повторного использования и создания открытых иерархий, в то время как sealed class — это способ создания безопасных ограниченных иерархий с исчерпывающей проверкой на уровне компиляции. Выбор между ними зависит от того, хотите ли вы расширяемую архитектуру (abstract class) или типобезопасное ограниченное множество вариантов (sealed class).

В чем разница между sealed class и абстрактным классом? | PrepBro