Що таке запечатана ознака?


332

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

Хотілося б знати, якщо запечатана ознака збігається із запечатаним класом? Або, якщо ні, які відмінності? Коли корисно використовувати запечатану ознаку (а коли ні)?

Відповіді:


472

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.
sscarduzio

1
дуже хороша ! і не тільки кінцевий і заздалегідь відомий, але також є частиною обмеженого (запечатаного?) контексту, де має сенс перевірити всі можливі підтипи, такі як так | ні, навіть | непарні тощо ...
Mário de Sá Vera

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 - досить пізня відповідь, але у випадку, якщо ви чи хтось інший зацікавлений: контекстне обмеження ( [A: F]) не працює так само, як обмеження дисперсії. Скоріше, саме синтаксичний цукор вимагає неявного F[A]обсягу. Зазвичай він використовується для виклику екземплярів typeclass способом, який трохи терміше і легше читати, ніж неявний параметр ( (implicit fa: F[A])), але він все одно працює точно так само під кришкою, і як вказує Даніель, ознаки не мають робити що.
mirichan

54

З щоденного блогу Scala :

Коли ознака "запечатана", всі її підкласи оголошуються в одному файлі, і це робить набір підкласів кінцевим, що дозволяє певні перевірки компілятора.


Дякую. Маючи на увазі "всі його підкласи", це означає класи та ознаки?
Джон Тріпвуд

@John - Я не пробував, але підозрюю заняття. Справа в герметизації полягає в тому, що все визначено в межах однієї вихідної одиниці
Брайана Агнева,

1
@JohnThreepwood: класи, риси та об'єкти. Найчастіше в Scala термін «клас» використовується для позначення класів, ознак та об’єктів. Тільки кажучи про специфічні відмінності між ними, це означає лише заняття. У SLS використовується термін "шаблон" для позначення як класів, так і ознак, але цей термін не використовується багато за межами SLS, і немає терміна, який би охоплював усі три класи, ознаки та об'єкти.
Йорг W Міттаг

30

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

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

- М. Одерський. Специфікація мови Scala, версія 2.8. онлайн, вересень, 2013 р.


7

Rief Коротко:

  • Запечатані ознаки можна розширити лише в одному файлі
  • Цей список дозволяє компілятору легко знати всі можливі підтипи
  • Використовуйте запечатані ознаки, коли кількість можливих підтипів є кінцевим і відомим заздалегідь
  • Спосіб створення чогось на зразок enum в Java
  • Допоможіть визначити алгебраїчні типи даних (ADT)

і для детальної інформації Все про запечатані риси в Scala

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.