Jika Anda menulis kode yang menggunakan banyak struktur data yang indah dan tidak dapat diubah, kelas kasus tampak seperti berkah, memberi Anda semua hal berikut secara gratis hanya dengan satu kata kunci:
- Semuanya tidak berubah secara default
- Getter ditentukan secara otomatis
- Penerapan toString () yang layak
- Patuh sama dengan () dan hashCode ()
- Objek pendamping dengan metode unapply () untuk pencocokan
Tapi apa kerugian dari mendefinisikan struktur data yang tidak dapat diubah sebagai kelas kasus?
Batasan apa yang diberlakukan pada kelas atau kliennya?
Adakah situasi di mana Anda harus memilih kelas non-case?
scala
case-class
Graham Lea
sumber
sumber
Jawaban:
Satu kerugian besar: kelas kasus tidak dapat memperluas kelas kasus. Itulah batasannya.
Keuntungan lain yang Anda lewatkan, tercantum untuk kelengkapan: serialisasi / deserialisasi yang sesuai, tidak perlu menggunakan kata kunci "baru" untuk membuat.
Saya lebih suka kelas non-case untuk objek dengan status bisa berubah, status privat, atau tanpa status (misalnya sebagian besar komponen tunggal). Kelas kasus untuk hampir semua hal lainnya.
sumber
Pertama, bagian yang bagus:
Semuanya tidak berubah secara default
Ya, dan bahkan dapat diganti (menggunakan
var
) jika Anda membutuhkannyaGetter ditentukan secara otomatis
Dimungkinkan di kelas mana pun dengan mengawali params dengan
val
toString()
Implementasi yang layakYa, sangat berguna, tetapi bisa dilakukan dengan tangan di kelas mana pun jika perlu
Sesuai
equals()
danhashCode()
Dikombinasikan dengan pencocokan pola yang mudah, inilah alasan utama orang menggunakan kelas kasus
Objek pendamping dengan
unapply()
metode pencocokanJuga memungkinkan untuk dilakukan dengan tangan di semua kelas dengan menggunakan ekstraktor
Daftar ini juga harus menyertakan metode penyalinan yang sangat kuat, salah satu hal terbaik yang akan datang ke Scala 2.8
Lalu yang buruk, hanya ada beberapa batasan nyata dengan kelas kasus:
Anda tidak dapat menentukan
apply
dalam objek pendamping menggunakan tanda tangan yang sama seperti metode yang dihasilkan kompilatorNamun dalam praktiknya, ini jarang menjadi masalah. Mengubah perilaku metode penerapan yang dihasilkan dijamin akan mengejutkan pengguna dan harus sangat tidak disarankan, satu-satunya alasan untuk melakukannya adalah dengan memvalidasi parameter masukan - tugas yang paling baik dilakukan di badan konstruktor utama (yang juga membuat validasi tersedia saat menggunakan
copy
)Anda tidak bisa membuat subkelas
Benar, meskipun kelas kasus masih mungkin menjadi turunannya sendiri. Salah satu pola umum adalah membangun hierarki kelas dari ciri-ciri, menggunakan kelas kasus sebagai simpul daun dari pohon.
sealed
Pengubah juga perlu diperhatikan . Setiap subclass dari suatu sifat dengan pengubah ini harus dideklarasikan dalam file yang sama. Saat pencocokan pola terhadap instance dari sifat tersebut, compiler kemudian dapat memperingatkan Anda jika Anda belum memeriksa semua kemungkinan subkelas konkret. Saat digabungkan dengan kelas kasus, ini dapat menawarkan tingkat kepercayaan yang sangat tinggi pada kode Anda jika dikompilasi tanpa peringatan.Sebagai subkelas Produk, kelas kasus tidak boleh memiliki lebih dari 22 parameter
Tidak ada solusi nyata, kecuali untuk berhenti menyalahgunakan kelas dengan parameter sebanyak ini :)
Juga...
Satu batasan lain yang kadang-kadang dicatat adalah bahwa Scala tidak (saat ini) mendukung parameter malas (seperti
lazy val
s, tetapi sebagai parameter). Solusi untuk ini adalah dengan menggunakan parameter menurut nama dan menetapkannya ke lazy val di konstruktor. Sayangnya, parameter dengan nama tidak bercampur dengan pencocokan pola, yang mencegah teknik yang digunakan dengan kelas kasus karena merusak ekstraktor yang dihasilkan kompiler.Ini relevan jika Anda ingin mengimplementasikan struktur data malas yang berfungsi tinggi, dan mudah-mudahan akan diselesaikan dengan penambahan parameter malas ke rilis Scala di masa mendatang.
sumber
Saya pikir prinsip TDD berlaku di sini: jangan mendesain berlebihan. Saat Anda mendeklarasikan sesuatu sebagai
case class
, Anda mendeklarasikan banyak fungsi. Itu akan mengurangi fleksibilitas yang Anda miliki dalam mengubah kelas di masa mendatang.Misalnya, a
case class
memilikiequals
metode di atas parameter konstruktor. Anda mungkin tidak peduli tentang itu ketika Anda pertama kali menulis kelas Anda, tetapi, terakhir, mungkin memutuskan Anda ingin kesetaraan mengabaikan beberapa parameter ini, atau melakukan sesuatu yang sedikit berbeda. Namun, kode klien dapat ditulis dalam waktu yang bergantung padacase class
kesetaraan.sumber
Martin Odersky memberi kita titik awal yang baik dalam kursusnya Prinsip-Prinsip Pemrograman Fungsional dalam Skala (Kuliah 4.6 - Pencocokan Pola) yang dapat kita gunakan ketika kita harus memilih antara kelas dan kelas kasus. Bab 7 Scala By Example berisi contoh yang sama.
Selain itu, menambahkan kelas Prod baru tidak memerlukan perubahan apa pun pada kode yang sudah ada:
Sebaliknya, menambahkan metode baru membutuhkan modifikasi semua kelas yang ada.
Masalah yang sama diselesaikan dengan kelas kasus.
Menambahkan metode baru adalah perubahan lokal.
Menambahkan kelas Prod baru membutuhkan kemungkinan mengubah semua pencocokan pola.
Transkrip dari videolecture 4.6 Pencocokan Pola
Ingat: kita harus menggunakan ini sebagai titik awal dan bukan sebagai satu-satunya kriteria.
sumber
Saya mengutip ini dari
Scala cookbook
olehAlvin Alexander
pasal 6:objects
.Ini adalah salah satu dari banyak hal yang menurut saya menarik dalam buku ini.
Untuk menyediakan beberapa konstruktor untuk kelas kasus, penting untuk mengetahui apa yang sebenarnya dilakukan deklarasi kelas kasus.
Jika Anda melihat kode yang dihasilkan kompilator Scala untuk contoh kelas kasus, Anda akan melihat bahwa kode tersebut membuat dua file keluaran, Person $ .class dan Person.class. Jika Anda membongkar Person $ .class dengan perintah javap, Anda akan melihat bahwa ini berisi metode terapan, bersama dengan banyak metode lainnya:
Anda juga dapat membongkar Person.class untuk melihat isinya. Untuk kelas sederhana seperti ini, ini berisi 20 metode tambahan; pembengkakan tersembunyi ini adalah salah satu alasan beberapa pengembang tidak menyukai kelas kasus.
sumber