Một đặc điểm kín là gì?


332

Các lớp kín được mô tả trong 'Lập trình trong Scala', nhưng các đặc điểm được niêm phong thì không. Tôi có thể tìm thêm thông tin về một đặc điểm kín ở đâu?

Tôi muốn biết, nếu một đặc điểm kín giống như một lớp kín? Hoặc, nếu không, sự khác biệt là gì? Khi nào nên sử dụng một đặc điểm kín (và khi không)?

Câu trả lời:


472

Một sealedđặc điểm chỉ có thể được mở rộng trong cùng một tệp với khai báo của nó.

Chúng thường được sử dụng để cung cấp một thay thế cho enums. Vì chúng chỉ có thể được mở rộng trong một tệp duy nhất, trình biên dịch biết mọi kiểu con có thể và có thể giải thích về nó.

Ví dụ với khai báo:

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

Trình biên dịch sẽ phát ra một cảnh báo nếu một trận đấu không đầy đủ:

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

Vì vậy, bạn nên sử dụng các đặc điểm kín (hoặc lớp trừu tượng kín) nếu số lượng các kiểu con có thể là hữu hạn và được biết trước. Để biết thêm ví dụ, bạn có thể xem danh sách và triển khai tùy chọn .


112
tôi mất sáu tháng để ngẫu nhiên đến đây và hiểu cách thay thế Java Enum trong Scala.
sscarduzio

rất đẹp ! và không chỉ hữu hạn và được biết trước mà còn là một phần của bối cảnh bị hạn chế (niêm phong?) trong đó có ý nghĩa để kiểm tra tất cả các kiểu con có thể như có | không, thậm chí | lẻ v.v ...
Mário de Sá Vera

90

một đặc điểm kín giống như một lớp kín?

Theo như sealedđi, có. Họ chia sẻ sự khác biệt bình thường giữa traitclass, tất nhiên.

Hoặc, nếu không, sự khác biệt là gì?

Moot

Khi nào nên sử dụng một đặc điểm kín (và khi không)?

Nếu bạn có một sealed class X, thì bạn phải kiểm tra Xcũng như bất kỳ lớp con nào. Điều tương tự không đúng với sealed abstract class Xhoặc sealed trait X. Vì vậy, bạn có thể làm sealed abstract class X, nhưng đó là cách dài dòng hơn là chỉ traitvà ít lợi thế.

Ưu điểm chính của việc sử dụng abstract classhơn a traitlà nó có thể nhận được các tham số. Lợi thế đó đặc biệt có liên quan khi sử dụng các loại lớp. Giả sử bạn muốn xây dựng một cây được sắp xếp, ví dụ. Bạn có thể viết điều này:

sealed abstract class Tree[T : Ordering]

nhưng bạn không thể làm điều này:

sealed trait Tree[T : Ordering]

vì giới hạn bối cảnh (và giới hạn xem) được thực hiện với các tham số ngầm. Cho rằng các đặc điểm không thể nhận được tham số, bạn không thể làm điều đó.

Cá nhân, tôi thích sealed traitvà sử dụng nó trừ khi một số lý do cụ thể khiến tôi sử dụng a sealed abstract class. Và tôi không nói về những lý do tinh tế, nhưng những lý do trực diện mà bạn không thể bỏ qua, chẳng hạn như sử dụng các lớp loại.


"vì giới hạn bối cảnh (và giới hạn khung nhìn) được triển khai với các tham số ngầm." - bạn có thể giải thích về điều đó?
Ruby

@Ruby - trả lời khá muộn, nhưng trong trường hợp bạn hoặc bất kỳ ai khác quan tâm: [A: F]ràng buộc bối cảnh ( ) không hoạt động giống như các ràng buộc phương sai. Thay vào đó, đó là đường cú pháp đòi hỏi một F[A]phạm vi ngầm . Nó thường được sử dụng để triệu tập các thể hiện kiểu chữ theo cách hơi khó đọc và dễ đọc hơn một tham số ẩn ( (implicit fa: F[A])), nhưng nó vẫn hoạt động theo cách chính xác theo cách thức và như Daniel chỉ ra, các đặc điểm không được thực hiện cái đó.
mirichan

54

Từ blog hàng ngày :

Khi một đặc điểm được "niêm phong", tất cả các lớp con của nó được khai báo trong cùng một tệp và điều đó làm cho tập hợp các lớp con hữu hạn cho phép kiểm tra trình biên dịch nhất định.


Cảm ơn bạn. Với "tất cả các lớp con của nó" nó có nghĩa là các lớp và đặc điểm?
John Threepwood

@ John - Tôi chưa thử, nhưng tôi nghi ngờ các lớp học. Điểm quan trọng về việc niêm phong là mọi thứ được xác định trong một đơn vị nguồn đó
Brian Agnew

1
@JohnThreepwood: các lớp, đặc điểm và đối tượng. Hầu hết thời gian, trong Scala, thuật ngữ "lớp" được sử dụng để chỉ các lớp, đặc điểm và đối tượng. Chỉ khi nói về sự khác biệt cụ thể giữa chúng, nó chỉ có nghĩa là các lớp. SLS sử dụng thuật ngữ "khuôn mẫu" để chỉ cả hai lớp và đặc điểm, nhưng thuật ngữ đó không được sử dụng nhiều ngoài SLS và không có thuật ngữ nào bao gồm cả ba lớp, tính trạng và đối tượng.
Jörg W Mittag

30

Ngoài ra tôi cảm thấy cần phải chỉ cho bạn các thông số kỹ thuật:

Các chế độ được niêm phong áp dụng cho các phiên bản lớp. Một lớp niêm phong có thể không được kế thừa trực tiếp, trừ khi mẫu kế thừa được định nghĩa trong cùng một tệp nguồn với lớp kế thừa. Tuy nhiên, các lớp con của một lớp kín có thể được kế thừa ở bất cứ đâu.

- M. Oderky. Đặc tả ngôn ngữ Scala, phiên bản 2.8. trực tuyến, tháng 9 năm 2013.


7

Tóm tắt:

  • Các đặc điểm được niêm phong chỉ có thể được mở rộng trong cùng một tệp
  • Liệt kê điều này cho phép trình biên dịch dễ dàng biết tất cả các kiểu con có thể
  • Sử dụng các đặc điểm kín khi số lượng các kiểu con có thể là hữu hạn và được biết trước
  • Một cách tạo ra một cái gì đó như enum trong Java
  • Trợ giúp xác định loại dữ liệu đại số (ADT)

và để biết thêm chi tiết Tất cả mọi thứ về các đặc điểm kín trong Scala

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.