Apa sifat tersegel?

332

Kelas tertutup dijelaskan dalam 'Pemrograman dalam Scala', tetapi sifat tertutup tidak. Di mana saya dapat menemukan informasi lebih lanjut tentang sifat yang disegel?

Saya ingin tahu, apakah sifat yang disegel sama dengan kelas yang disegel? Atau, jika tidak, apa perbedaannya? Kapan ide yang baik untuk menggunakan sifat tersegel (dan kapan tidak)?

John Threepwood
sumber

Jawaban:

473

Suatu sealedsifat dapat diperpanjang hanya dalam file yang sama dengan deklarasi.

Mereka sering digunakan untuk memberikan alternatif enums. Karena mereka hanya dapat diperluas dalam satu file, kompiler mengetahui setiap subtipe yang mungkin dan dapat mempertimbangkannya.

Misalnya dengan deklarasi:

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

Kompiler akan mengeluarkan peringatan jika kecocokan tidak lengkap:

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

Jadi, Anda harus menggunakan sifat tersegel (atau kelas abstrak tersegel) jika jumlah subtipe yang mungkin terbatas dan diketahui sebelumnya. Untuk lebih banyak contoh, Anda dapat melihat daftar dan implementasi opsi .

paradigmatik
sumber
113
butuh waktu enam bulan untuk tiba secara acak di sini dan memahami cara mengganti Java Enum di Scala.
sscarduzio
1
sangat bagus ! dan tidak hanya terbatas dan diketahui sebelumnya tetapi juga bagian dari konteks terbatas (tersegel?) di mana masuk akal untuk memeriksa semua subtipe yang mungkin seperti ya | tidak, bahkan | aneh dll ...
Mário de Sá Vera
90

sifat tersegel adalah sama dengan kelas tersegel?

Sejauh ini sealed, ya. Mereka berbagi perbedaan normal antara traitdan class, tentu saja.

Atau, jika tidak, apa perbedaannya?

Moot.

Kapan ide yang baik untuk menggunakan sifat tersegel (dan kapan tidak)?

Jika Anda memiliki sealed class X, maka Anda harus memeriksa Xdan juga setiap subclass. Hal yang sama tidak berlaku untuk sealed abstract class Xatau sealed trait X. Jadi Anda bisa melakukannya sealed abstract class X, tetapi itu jauh lebih bertele-tele daripada hanya traitdan untuk sedikit keuntungan.

Keuntungan utama menggunakan abstract classover traitadalah dapat menerima parameter. Keuntungan itu sangat relevan ketika menggunakan kelas tipe. Katakanlah Anda ingin membuat pohon yang disortir, misalnya. Anda dapat menulis ini:

sealed abstract class Tree[T : Ordering]

tetapi Anda tidak dapat melakukan ini:

sealed trait Tree[T : Ordering]

karena batas konteks (dan batas tampilan) diimplementasikan dengan parameter implisit. Mengingat bahwa sifat tidak dapat menerima parameter, Anda tidak dapat melakukannya.

Secara pribadi, saya lebih suka sealed traitdan menggunakannya kecuali beberapa alasan tertentu membuat saya menggunakan a sealed abstract class. Dan saya tidak berbicara tentang alasan yang halus, tetapi alasan yang tidak bisa Anda abaikan, seperti menggunakan kelas tipe.

Daniel C. Sobral
sumber
"karena batas konteks (dan batas tampilan) diimplementasikan dengan parameter implisit." - bisakah Anda menguraikan hal itu?
Ruby
@ Ruby - balasan cukup terlambat, tetapi jika Anda atau orang lain tertarik: konteks bounding ( [A: F]) tidak bekerja dengan cara yang sama seperti batasan varians. Sebaliknya, itu gula sintaksis yang menuntut F[A]ruang lingkup implisit . Ini umumnya digunakan untuk memanggil instance typeclass dengan cara yang sedikit terser dan lebih mudah dibaca daripada parameter implisit ( (implicit fa: F[A])), tetapi masih bekerja dengan cara yang persis sama di bawah tenda, dan seperti yang ditunjukkan Daniel, sifat-sifat tidak bisa dilakukan bahwa.
mirichan
54

Dari blog scala harian :

Ketika suatu sifat "disegel" semua subclassnya dideklarasikan dalam file yang sama dan itu membuat himpunan subclass terbatas yang memungkinkan pemeriksaan kompiler tertentu.

Brian Agnew
sumber
Terima kasih. Dengan "semua subkelasnya" itu berarti kelas dan sifat?
John Threepwood
@ John - Saya belum mencoba, tapi saya curiga kelas. Poin tentang penyegelan adalah bahwa segala sesuatu didefinisikan dalam satu unit sumber
Brian Agnew
1
@JohnThreepwood: kelas, ciri dan objek. Sebagian besar waktu, di Scala, istilah "kelas" digunakan untuk merujuk ke kelas, sifat dan objek. Hanya ketika berbicara tentang perbedaan spesifik di antara mereka, itu berarti hanya kelas. SLS menggunakan istilah "templat" untuk merujuk ke kedua kelas dan sifat, tetapi istilah itu tidak banyak digunakan di luar SLS, dan tidak ada istilah yang mencakup ketiga kelas, sifat dan objek.
Jörg W Mittag
30

Saya juga merasa perlu mengarahkan Anda ke spesifikasi:

The disegel modi fi er berlaku untuk kelas de definisi fi. Kelas yang disegel mungkin tidak secara langsung diwarisi, kecuali jika templat yang diturunkan didefinisikan dalam file sumber yang sama dengan kelas yang diwarisi. Namun, subclass dari kelas yang disegel dapat diwarisi di mana saja.

- M. Odersky. Spesifikasi bahasa Scala, versi 2.8. online, September 2013.

DI
sumber
7

secara singkat:

  • Ciri tersegel hanya dapat diperpanjang dalam file yang sama
  • Daftar ini memungkinkan kompiler mengetahui semua subtipe yang mungkin dengan mudah
  • Gunakan sifat tersegel ketika jumlah subtipe yang mungkin terbatas dan diketahui sebelumnya
  • Cara membuat sesuatu seperti enum di Jawa
  • Membantu mendefinisikan tipe data aljabar (ADT)

dan untuk lebih jelasnya Segala sesuatu tentang sifat tersegel di Scala

Majid Hosseini
sumber