2012-06-26 20 views
264

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

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

Trả lời

42

Từ daily-scala blog:

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

+0

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

+1

Được bỏ phiếu tại sao? –

+0

@ John - Tôi đã không cố gắng, nhưng tôi nghi ngờ các lớp học. Điểm về niêm phong là mọi thứ được xác định trong một đơn vị nguồn đó –

354

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

Chúng thường được sử dụng để 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 tất cả các kiểu con có thể và có thể giải thích về nó.

Ví dụ với việc kê khai:

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 phải là đầ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 

đặc điểm Vì vậy, bạn nên sử dụng bịt kín (hoặc kín lớp trừu tượng) 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 qua các triển khai listoption.

+78

nó đã cho tôi sáu tháng để ngẫu nhiên đến đây và hiểu làm thế nào để thay thế Java Enum trong Scala. – sscarduzio

77

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

Theo như sealed, 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 thì tốt hơn nên sử dụng đặc điểm được niêm phong (và khi nào không)?

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

Ưu điểm chính của việc sử dụng abstract class trên trait là nó có thể nhận thông số. Lợi thế đó đặc biệt phù hợp khi sử dụng các lớp kiểu. Ví dụ: giả sử bạn muốn tạo một cây đã được sắp xếp.Bạn có thể viết 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] 

kể từ khi giới hạn ngữ cảnh (và xem giới hạn) được thực hiện với các thông số ngầm. Do các đặc điểm không thể nhận được các thông số, bạn không thể làm điều đó.

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

+0

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

22

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 kín Modi fi er áp dụng cho nitions fi lớp de. Một lớp kín có thể không được kế thừa trực tiếp, ngoại trừ nếu mẫu kế thừa được xác định trong cùng một nguồn tệp làm lớp được kế thừa. Tuy nhiên, các lớp con của một lớp niêm phong có thể được thừa hưởng ở bất kỳ đâu.

- M. Odersky. The Scala language specification, version 2.8. online, Sept., 2013.

Các vấn đề liên quan