Статьи Kotlin. Изолированные (запечатанные) классы (sealed classes).
Post
Cancel

Kotlin. Изолированные (запечатанные) классы (sealed classes).

Изолированный класс - это еще одно новшество в языке Kotlin, которого не было в Java. Тем не менее, само по себе понятие в программировании не является новым — Kotlin позаимствовал его у других языков.

В официальной документации изолированному классу было дано такое определение: класс, который позволяет ограничить иерархию классов конкретным множеством подтипов, каждый из которых может определять собственные свойства и функции. На мой взгляд, формулировка не особо понятна.

Если говорить проще, то это абстрактный класс, который содержит в себе другие классы. По концепции очень похоже на enum, но с суперсилой. Выражена эта суперсила в том, что позволяет высвободиться от минусов enum. А именно:

  • В enum каждое значение - это константа, которая существует в единственном экземпляре. Значение константы нельзя подстроить под конкретную ситуацию, потому что при изменении значения в одном месте, оно изменится везде. В изолированном же классе можно создать столько подклассов, сколько необходимо для покрытия каждой ситуации. Помимо этого, каждый подкласс может иметь несколько экземпляров, каждый из которых будет нести в себе свое собственное состояние.
  • Каждое значение в enum должно содержать одинаковый набор свойств. Не получится какому-либо значению задать дополнительное свойство. Напротив, каждый подкласс изолированного класса имеет свой конструктор со своими индивидуальными свойствами.

Для определения изолированного класса используется ключевое слово sealed.

1
2
3
4
sealed class MessageType {
  class Success(var msg: String) : MessageType()
  class Failure(var msg: String, var e: Exception) : MessageType()
}

В данном примере класс MessageType является изолированным. У него есть два подкласса-наследника - Success() и Failure(), каждый из которых имеет индивидуальный набор свойств. Тут может возникнуть вопрос: как Success() и Failure() могут наследоваться от MessageType(), если он не отмечен ключевым словом open? Всё просто: изолированный класс “открыт” для наследования по умолчанию, и дополнительно указывать слово open не требуется.

Также обратите внимание, что несмотря на то, что изолированный класс может иметь наследников, все они должны быть перечислены в одном с ним файле. Однако классы, которые расширяют наследников изолированного класса могут находиться где угодно.

Помимо этого, изолированный класс абстрактен по умолчанию и может содержать в себе абстрактные компоненты.

Изолированный класс можно использовать совместно с условным выражением when, при этом указывать ветку else не требуется.

1
2
3
4
5
6
7
8
val msgSuccess = Success("Ура!")
val msgFailure = Failure("Ну вот...", Exсeption("Что-то пошло не так."))
var messageType: MessageType = msgFailure

val msg = when(messageType) {
  is Success -> messageType.msg
  is Failure -> messageType.msg + " " + messageType.e.message
}

На данный момент об изолированных классах сказать больше нечего. Поэтому резюмируем:

  • Изолированные классы - это enum с суперсилой.
  • У изолированного класса могут быть наследники, но все они должны находиться в одном файле с изолированным классом. Классы, которые расширяют наследников изолированного класса могут находиться где угодно.
  • Изолированные классы абстрактны и могут содержать в себе абстрактные компоненты.
  • Конструктор изолированного класса всегда приватен, и это нельзя изменить.
  • Изолированные классы нельзя инициализировать.
  • Наследники изолированного класса могут быть классами любого типа: классом данных, объектом, обычным классом или даже другим изолированным классом.

Полезные ссылки

Sealed Classes - официальная документация.
Изолированные классы - перевод на русский.

This post is licensed under CC BY 4.0 by the author.

Kotlin. Вложенные и внутренние классы

Kotlin. Проверь себя! Вопросы - ответы.