Изолированный класс - это еще одно новшество в языке 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 - официальная документация.
Изолированные классы - перевод на русский.