English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
В этой статье вы узнаете о сеaled (запечатанных) классах с помощью примеров, как их создавать и когда использовать.
Сеaled классы используются, когда значения могут быть включены только из ограниченного набора (ограниченной иерархии) типов.
До того как мы более подробно рассмотрим сеaled классы, давайте рассмотрим проблемы, которые они решают. Давайте рассмотрим пример:
class Expr class Const(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) else -> throw IllegalArgumentException("Unknown expression") }
В данном примере базовый класс Expr имеет два производных класса Const (представляющий число) и Sum (представляющий сумму выражений). Здесь необходимо использовать ветвь else для обработки в выражениях whenпо умолчанию.
Теперь, если вы производите новый подкласс от класса Expr, компилятор не будет обнаруживать ничего, так как ветвь else будет обрабатывать её, что может привести к ошибке. Если компилятор выдаст ошибку при добавлении нового подкласса, то это лучше.
Чтобы решить эту проблему, можно использовать сеaled классы. Как уже говорилось, сеaled классы ограничивают возможность создания подклассов. И когда вы обрабатываете все подклассы сеaled классов в выражениях when, вам не нужно использовать ветвь else.
Чтобы создать сеaled класс, используйте модификатор sealed. Например:
sealed class Expr
Вот метод решения этой проблемы с использованием сеaled классов:
sealed class Expr class Const(val value: Int) : Expr() class Sum(val left: Expr, val right: Expr) : Expr() object NotANumber : Expr() fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) NotANumber -> java.lang.Double.NaN }
Как вы видите, нет ELSE-ветви. Если вы производите новый подкласс от класса Expr,除非 подкласс обрабатывается в when-выражении,否则 компилятор будет сообщать.
Все подклассы секретного класса должны быть объявлены в том же файле, что и сам секретный класс.
Сам секретный классАбстрактныйВы не можете instantiate объект из него.
Нельзя создать несекретный конструктор для секретного класса; по умолчанию их конструктор private.
Классы энумОни очень похожи. Значения энумов также ограничены, как и у секретных классов.
Единственное отличие заключается в том, что энум может иметь только один экземпляр, в то время как у подклассов секретного класса может быть несколько экземпляров.