Jika saya menggunakan un disegel trait
atau abstract class
dalam Scala dan kemudian menggunakan pencocokan pola, saya bertanya-tanya, apakah kompiler tidak tahu pada waktu kompilasi untuk patternmatch khusus ini apa implementasi yang mungkin dari sifat / kelas ini yang tersedia? Jadi, jika ya, bisakah itu tidak memberikan peringatan kecocokan pola meskipun trait
/ abstract class
tidak disegel karena dia tahu jenis mana yang dapat digunakan, dengan memeriksa semua kemungkinan dependensi / impor?
Misalnya jika saya memiliki Option[A]
dan saya melakukan pencocokan pola hanya untuk Some[A]
tetapi tidak untuk None
, kompiler akan mengeluh, karena Option
disegel.
Jika kompiler tidak dapat mengetahui / menyelesaikannya, lalu mengapa dia tidak bisa? Dan jika kompiler (secara teoritis) dapat melakukan itu, apa alasan untuk itu tidak digunakan dalam Scala? Apakah ada bahasa lain yang mendukung perilaku semacam itu?
sumber
Foo
dengan subclassA
,B
danC
, dan semua pertandingan pola cocok hanya tiga. Tidak ada yang menghentikan saya untuk menambahkan subclass baruD
yang akan meledakkan kecocokan pola Anda.java.lang.ClassLoader
.Jawaban:
Mencari tahu semua subclass dari suatu kelas disebut Analisis Hirarki Kelas, dan melakukan CHA statis dalam bahasa dengan pemuatan kode dinamis setara dengan menyelesaikan Masalah Pemutusan.
Plus, salah satu tujuan Scala adalah kompilasi dan penyebaran modul independen yang terpisah, sehingga kompiler tidak dapat mengetahui apakah suatu kelas disubklasifikasi dalam modul lain, karena ia tidak pernah melihat lebih dari satu modul. (Setelah semua, Anda dapat mengkompilasi modul terhadap antarmuka beberapa modul lain tanpa modul itu ada di sistem Anda!) Itu sebabnya
sealed
mengharuskan semua subclass harus didefinisikan dalam unit kompilasi yang sama.Itu juga salah satu alasan mengapa JVM dapat bersaing dengan baik dengan kompiler C ++: Kompiler C ++ biasanya adalah kompiler statis, sehingga mereka secara umum tidak dapat mengetahui apakah suatu metode ditimpa atau tidak, dan dengan demikian tidak dapat menyejajarkannya. JVM OTOH, biasanya adalah kompiler dinamis, mereka tidak perlu melakukan CHA untuk mengetahui apakah suatu metode ditimpa atau tidak, mereka hanya dapat melihat Hierarki Kelas saat runtime. Dan bahkan jika pada titik selanjutnya dalam pelaksanaan program subclass baru datang yang tidak ada sebelumnya, bukan masalah besar, hanya mengkompilasi ulang potongan kode tanpa inline.
Catatan: semua ini hanya berlaku dalam Scala. JVM tidak memiliki gagasan tentang
sealed
, jadi sangat mungkin untuk mensubkelassealed
kelas dari bahasa JVM lain , karena tidak ada cara untuk mengkomunikasikan hal ini ke bahasa lain. Thesealed
properti dicatat dalamScalaSig
penjelasan, tapi kompiler bahasa lain tidak mengambil orang-orang penjelasan ke rekening, jelas.sumber
Hal ini dapat dilakukan (setidaknya untuk semua kelas yang diketahui pada waktu kompilasi), itu hanya mahal. Anda benar-benar akan menghancurkan kompilasi tambahan, karena semua yang berisi kecocokan pola harus dikompilasi ulang setiap kali file lain diubah.
Dan apa yang kamu beli? Adalah bau kode untuk menulis kecocokan pola yang perlu sering diubah ketika kelas turunan baru ditambahkan. Ini merupakan pelanggaran prinsip terbuka / tertutup . Gunakan warisan dengan benar dan Anda tidak perlu menulis jenis kecocokan pola tersebut. Dan ya, prinsip terbuka / tertutup juga berlaku untuk bahasa fungsional tanpa pewarisan berbasis kelas. Bahkan di antara fitur-fitur seperti kelas tipe, multimethod, dan sekadar fungsi tingkat tinggi, bahasa fungsional membuat ekstensi tanpa modifikasi jauh lebih mudah.
sumber
It can be done (at least for all classes known at compile time), it's just expensive.
Tetapi jika program ini tidak 100% mandiri (yaitu tergantung pada.jar
file eksternal ), tidak bisakah Anda menyelinap di subkelas baru setelah kompilasi melalui salah satu darijar
s? Jadi kompilator dapat memberi tahu Anda "Kecocokan pola Anda sudah lengkap sekarang, tetapi itu dapat berubah jika ada dari dependensi Anda yang berubah" yang sangat tidak berharga karena titik memiliki dependensi eksternal adalah untuk dapat memperbaruinya tanpa kompilasi ulang!