Что такое запечатанная черта?

332

Запечатанные классы описаны в «Программирование в Scala», но запечатанные черты - нет. Где я могу найти больше информации о запечатанном признаке?

Я хотел бы знать, является ли запечатанная черта такой же, как у запечатанного класса? Или, если нет, в чем различия? Когда стоит использовать запечатанную черту (а когда нет)?

Джон Трипвуд
источник

Ответы:

473

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

Поэтому вы должны использовать запечатанные черты (или запечатанный абстрактный класс), если число возможных подтипов конечно и известно заранее. Для большего количества примеров вы можете взглянуть на список и реализации опций .

образцовый
источник
113
Мне потребовалось шесть месяцев, чтобы случайно прибыть сюда и понять, как заменить Java Enum в Scala.
Скардузио
1
очень хорошо ! и не только конечный и известный заранее, но также и часть ограниченного (закрытого?) контекста, где имеет смысл проверить все возможные подтипы, такие как да | нет, даже | странный и т.д ...
Марио де Вера
90

Запечатанная черта - это то же самое, что запечатанный класс?

Что касается 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. И я говорю не о тонких причинах, а о личных причинах, которые вы не можете игнорировать, таких как использование классов типов.

Даниэль С. Собрал
источник
«поскольку границы контекста (и границы представления) реализованы с неявными параметрами». - не могли бы вы уточнить это?
Ruby
@Ruby - довольно поздний ответ, но в случае, если вы или кто-либо еще заинтересован: контекстное ограничение ( [A: F]) не работает так же, как ограничения на дисперсию. Скорее, это синтаксический сахар, требующий неявного F[A]охвата. Обычно он используется для вызова экземпляров классов типов таким способом, который немного сложнее и проще для чтения, чем неявный параметр ( (implicit fa: F[A])), но он все еще работает точно так же, как и Дэниел, и, как указывает Дэниел, черты не могут быть выполнены который.
Миричан
54

Из блога daily-scala :

Когда признак «запечатан», все его подклассы объявляются в одном и том же файле, и это делает набор подклассов конечным, что позволяет выполнять определенные проверки компилятором.

Брайан Агнью
источник
Спасибо. «Все его подклассы» означают классы и черты?
Джон Трипвуд
@ Джон - я не пробовал, но подозреваю, что уроки. Суть в том, что запечатывание заключается в том, что все определено в пределах одной исходной единицы
Брайан Агнью,
1
@JohnThreepwood: классы, черты и объекты. В Scala большую часть времени термин «класс» используется для обозначения классов, признаков и объектов. Только когда речь идет о конкретных различиях между ними, это означает только занятия. SLS использует термин «шаблон» для обозначения как классов, так и признаков, но этот термин мало используется за пределами SLS, и нет термина, который охватывает все три класса, признаки и объекты.
Йорг Миттаг
30

Также я чувствую необходимость указать вам спецификации:

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

- М. Одерский. Спецификация языка Scala, версия 2.8. в сети, сентябрь 2013 г.

В
источник
7

Кратко:

  • Запечатанные черты могут быть расширены только в одном файле
  • Список это позволяет компилятору легко узнать все возможные подтипы
  • Используйте запечатанные черты, когда число возможных подтипов конечно и известно заранее
  • Способ создания чего-то вроде enum в Java
  • Помогите определить алгебраические типы данных (ADT)

и более подробно все о запечатанных чертах в Scala

Маджид Хоссейни
источник