Запечатанные классы описаны в разделе "Программирование в Scala", но опечатанные черты - нет. Где я могу найти дополнительную информацию о запечатанном признаке?
Я хотел бы знать, если запечатанная черта совпадает с запечатанным классом? Или, если нет, каковы различия? Когда это хорошая идея использовать запечатанную черту (а когда нет)?
A sealed
признак может быть расширен только в том же файле, что и его объявление.
Они часто используются для обеспечения альтернативы enums
. Поскольку они могут быть расширены только в одном файле, компилятор знает все возможные подтипы и может рассуждать об этом.
Например, с объявлением:
sealed trait Answer
case object Yes extends Answer
case object No extends Answer
Компилятор выдаст предупреждение, если совпадение не является исчерпывающим:
scala> val x: Answer = Yes
x: Answer = Yes
scala> x match {
| case No => println("No")
| }
<console>:12: warning: match is not exhaustive!
missing combination Yes
Таким образом, вы должны использовать закрытые черты (или замкнутый абстрактный класс), если количество возможных подтипов конечно и известно заранее. Для получения дополнительных примеров вы можете взглянуть на list и option.
Запечатанный признак совпадает с запечатанным классом?
Что касается sealed
, да. Разумеется, они разделяют нормальные различия между trait
и class
.
Или, если нет, каковы различия?
Мут.
Когда это хорошая идея использовать запечатанный признак (а когда нет)?
Если у вас есть sealed class X
, вам необходимо проверить X
, а также любые подклассы. То же самое не относится к sealed abstract class X
или sealed trait X
. Таким образом, вы можете сделать sealed abstract class X
, но тем более более подробным, чем просто trait
и для небольшого преимущества.
Основным преимуществом использования abstract class
над a trait
является то, что он может принимать параметры. Это преимущество особенно важно при использовании классов типов. Скажем, вы хотите, например, построить отсортированное дерево. Вы можете написать это:
sealed abstract class Tree[T : Ordering]
но вы не можете этого сделать:
sealed trait Tree[T : Ordering]
поскольку границы контекста (и границы обзора) реализуются с неявными параметрами. Учитывая, что черты не могут получать параметры, вы не можете этого сделать.
Лично я предпочитаю sealed trait
и использую его, если только по какой-то определенной причине я не использую sealed abstract class
. И я не говорю о тонких причинах, но по-вашему-причинам вы не можете игнорировать, например, используя классы типов.
Когда черта "запечатана", все ее подклассы объявляются в пределах тот же файл и делает набор подклассов конечным, что позволяет некоторые проверки компилятора.
Также я считаю необходимым указать вам спецификации:
Модификация с печатью применяется к определениям классов. Класс с печатью не может быть непосредственно унаследован, за исключением случаев, когда наследующий шаблон определяется в том же источнике файл как унаследованный класс. Однако подклассы закрытого класса могут быть унаследованы где угодно.
- M. Одерски. Спецификация языка Scala, версия 2.8. онлайн, сентябрь, 2013 г.