Co to jest zapieczętowana cecha?


332

Zapieczętowane klasy są opisane w „Programowaniu w Scali”, ale zapieczętowane cechy nie są. Gdzie mogę znaleźć więcej informacji na temat zapieczętowanej cechy?

Chciałbym wiedzieć, czy zapieczętowana cecha jest taka sama jak zapieczętowana klasa? A jeśli nie, jakie są różnice? Kiedy warto zastosować zapieczętowaną cechę (a kiedy nie)?

Odpowiedzi:


472

sealedCecha może być przedłużony tylko w tym samym pliku, co jego deklaracji.

Są często używane jako alternatywa dla enums. Ponieważ można je rozszerzyć tylko w jednym pliku, kompilator zna wszystkie możliwe podtypy i może o tym uzasadnić.

Na przykład z deklaracją:

sealed trait Answer
case object Yes extends Answer
case object No extends Answer

Kompilator wyśle ​​ostrzeżenie, jeśli dopasowanie nie jest wyczerpujące:

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

Dlatego powinieneś używać zapieczętowanych cech (lub zapieczętowanej klasy abstrakcyjnej), jeśli liczba możliwych podtypów jest skończona i znana z góry. Więcej przykładów można znaleźć na liście i implementacjach opcji .


113
Losowo przybyłem tutaj i zrozumiałem, jak zastąpić Java Enum w Scali.
sscarduzio

1
bardzo dobrze ! i nie tylko skończone i znane z góry, ale także część ograniczonego (zapieczętowanego?) kontekstu, w którym sensowne jest sprawdzenie wszystkich możliwych podtypów, takich jak yes | nie, nawet | nieparzyste itp ...
Mário de Sá Vera

90

zapieczętowana cecha jest taka sama jak zapieczętowana klasa?

Jeśli chodzi o sealedtak, to tak. Dzielą normalne różnice między traiti class, oczywiście.

A jeśli nie, jakie są różnice?

Sporny.

Kiedy warto zastosować zapieczętowaną cechę (a kiedy nie)?

Jeśli masz sealed class X, musisz sprawdzić, Xjak również wszelkie podklasy. To samo nie dotyczy sealed abstract class Xlub sealed trait X. Więc możesz to zrobić sealed abstract class X, ale jest to o wiele bardziej szczegółowe niż tylko traiti ma niewielką przewagę.

Główną zaletą używania abstract classa traitjest to, że może odbierać parametry. Ta zaleta jest szczególnie istotna przy stosowaniu klas typów. Załóżmy na przykład, że chcesz zbudować posortowane drzewo. Możesz to napisać:

sealed abstract class Tree[T : Ordering]

ale nie możesz tego zrobić:

sealed trait Tree[T : Ordering]

ponieważ granice kontekstu (i granice widoku) są implementowane z niejawnymi parametrami. Ponieważ cechy nie mogą odbierać parametrów, nie możesz tego zrobić.

Osobiście wolę sealed traiti używam go, chyba że jakiś konkretny powód zmusza mnie do używania sealed abstract class. I nie mówię o subtelnych powodach, ale o powodach, których nie możesz zignorować, takich jak stosowanie klas typów.


„ponieważ granice kontekstu (i granice widoku) są implementowane z niejawnymi parametrami”. - czy mógłbyś to rozwinąć?
Ruby,

@Ruby - dość późna odpowiedź, ale na wypadek, gdybyś był zainteresowany: ograniczanie kontekstu ( [A: F]) nie działa tak samo jak ograniczenia wariancji. Przeciwnie, to cukier składniowy wymaga niejawnego F[A]zakresu. Zwykle jest używany do przywoływania instancji klasowych w sposób nieco bardziej przejrzysty i łatwiejszy do odczytania niż parametr niejawny ( (implicit fa: F[A])), ale nadal działa dokładnie tak samo pod maską, a jak zauważa Daniel, cechy nie są do zrobienia że.
mirichan

54

Z codziennego bloga Scala :

Gdy cecha jest „zapieczętowana”, wszystkie jej podklasy są deklarowane w tym samym pliku, co powoduje, że zbiór podklas jest skończony, co umożliwia pewne sprawdzanie kompilatora.


Dziękuję Ci. Z „wszystkimi podklasami” oznacza klasy i cechy?
John Threepwood,

@John - nie próbowałem, ale podejrzewam zajęcia. Chodzi o to, że pieczęć jest taka, że ​​wszystko jest zdefiniowane w tej jednej jednostce źródłowej
Brian Agnew,

1
@JohnThreepwood: klasy, cechy i przedmioty. Przez większość czasu w Scali termin „klasa” jest używany w odniesieniu do klas, cech i przedmiotów. Tylko mówienie o konkretnych różnicach między nimi oznacza tylko klasy. SLS używa terminu „szablon” w odniesieniu zarówno do klas, jak i cech, ale termin ten nie jest używany zbyt często poza SLS i nie ma terminu obejmującego wszystkie trzy klasy, cechy i obiekty.
Jörg W Mittag,

30

Czuję też potrzebę wskazania specyfikacji:

Uszczelnione Modi fi er dotyczy klasy Definicje. Uszczelnione klasa nie może być bezpośrednio dziedziczona, chyba że szablon dziedziczenie jest z definicją w tym samym pliku źródłowego jako dziedziczonej klasy. Jednak podklasy zapieczętowanej klasy mogą być dziedziczone w dowolnym miejscu.

- M. Odersky. Specyfikacja języka Scala, wersja 2.8. online, wrzesień 2013 r.


7

krótko:

  • Zapieczętowane cechy można rozszerzyć tylko w tym samym pliku
  • Lista ta pozwala kompilatorowi łatwo poznać wszystkie możliwe podtypy
  • Użyj zapieczętowanych cech, gdy liczba możliwych podtypów jest skończona i znana z góry
  • Sposób tworzenia czegoś takiego jak wyliczanie w Javie
  • Pomoc w definiowaniu algebraicznych typów danych (ADT)

i po więcej szczegółów Wszystko o zapieczętowanych cechach w Scali

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.