Melihat melalui Java Collections Framework, saya perhatikan beberapa antarmuka memiliki komentar (optional operation)
. Metode-metode ini memungkinkan kelas implementasi melalui UnsupportedOperationException
jika mereka tidak ingin mengimplementasikan metode itu.
Contoh dari ini adalah addAll
metode dalam Set Interface
.
Sekarang, seperti yang dinyatakan dalam rangkaian pertanyaan ini, antarmuka adalah kontrak yang menentukan untuk apa yang bisa digunakan oleh penggunaan.
Antarmuka penting karena mereka memisahkan apa yang dilakukan kelas dari bagaimana melakukannya. Kontrak yang mendefinisikan apa yang dapat diharapkan klien membuat pengembang bebas menerapkannya dengan cara apa pun yang mereka pilih, selama mereka menegakkan kontrak.
dan
Antarmuka adalah deskripsi tindakan yang dapat dilakukan suatu objek ... misalnya ketika Anda membalik sakelar lampu, lampu menyala, Anda tidak peduli bagaimana, hanya saja fungsinya. Dalam Pemrograman Berorientasi Objek, Interface adalah deskripsi dari semua fungsi yang harus dimiliki suatu objek agar menjadi "X".
dan
Saya pikir pendekatan berbasis antarmuka secara signifikan lebih baik. Anda kemudian dapat mengejek dependensi Anda dengan baik, dan semuanya pada dasarnya kurang erat.
Antarmuka + Ekstensi (mixin) vs Kelas Dasar
Mengingat bahwa tujuan dari antarmuka adalah untuk menentukan kontrak dan membuat dependensi Anda digabungkan secara longgar, tidakkah ada beberapa metode yang melemparkan UnsupportedOperationException
semacam kekalahan tujuannya? Itu berarti saya tidak bisa lagi menggunakan Set
dan hanya menggunakan addAll
. Sebaliknya, saya harus tahu implementasi apa yang Set
saya lewati, jadi saya bisa tahu apakah saya bisa menggunakan addAll
atau tidak. Bagi saya itu sepertinya tidak berharga.
Jadi apa gunanya UnsupportedOperationException
? Apakah ini hanya untuk mengganti kode lama, dan mereka perlu membersihkan antarmuka mereka? Atau apakah itu memiliki tujuan yang lebih masuk akal yang saya lewatkan?
sumber
addAll
diHashSet
. Itu mengacu pada implementasi default diAbstractCollection
mana pasti tidak membuangUnsupportedOperationException
.src.zip
ia bekerja dengan baik. Ini membantu untuk mengetahui persis kode apa yang JRE jalankan kadang-kadang dan tidak tunduk pada JavaDoc yang bisa sedikit bertele-tele.Jawaban:
Lihatlah antarmuka berikut:
Semua antarmuka ini menyatakan metode mutasi sebagai opsional. Ini secara implisit mendokumentasikan fakta bahwa kelas Collections mampu mengembalikan implementasi dari antarmuka yang tidak dapat diubah: yaitu, operasi-operasi mutasi opsional dijamin gagal. Namun, sesuai kontrak dalam JavaDoc, semua implementasi antarmuka tersebut harus mengizinkan operasi baca. Ini termasuk implementasi "normal" seperti
HashSet
danLinkedList
juga pembungkus abadi diCollections
.Berbeda dengan antarmuka antrian:
Antarmuka ini tidak menentukan operasi opsional: antrian, menurut definisi, dirancang untuk menawarkan dan mem-polling elemen dengan cara FIFO. Antrian abadi sama bermanfaatnya dengan mobil tanpa roda.
Satu gagasan umum yang muncul berulang kali adalah memiliki hierarki warisan yang memiliki objek yang dapat berubah dan tidak dapat diubah. Namun, semua ini memiliki kekurangan. Kompleksitas membuat air berlumpur tanpa benar-benar menyelesaikan masalah.
Hipotetis
Set
dapat memiliki operasi baca, dan subinterfaceMutableSet
dapat memiliki operasi tulis. Liskov memberi tahu kita bahwa aMutableSet
kemudian dapat diteruskan ke apa pun yang membutuhkan aSet
. Pada awalnya ini terdengar baik-baik saja, tetapi pertimbangkan metode yang mengharapkan set yang mendasarinya tidak akan dimodifikasi saat membaca: akan ada kemungkinan untuk dua utas menggunakan set yang sama dan melanggar invarian set yang tidak berubah. Ini dapat menyebabkan masalah misalnya jika suatu metode membaca elemen dari set dua kali dan itu ada di sana pertama kali tetapi tidak kedua kalinya.Set
bisa tidak memiliki implementasi langsung, sebaliknya memilikiMutableSet
danImmutableSet
sebagai subinterfaces yang kemudian digunakan untuk mengimplementasikan kelas. Ini memiliki masalah yang sama seperti di atas: pada beberapa titik dalam hierarki, antarmuka memiliki invarian yang saling bertentangan. Yang satu mengatakan "set ini harus bisa berubah" dan yang lain mengatakan "set ini tidak dapat berubah."Mungkin ada dua hierarki yang benar-benar terpisah untuk struktur data yang bisa berubah dan tidak berubah. Ini menambahkan satu ton kompleksitas ekstra untuk apa yang akhirnya menjadi sangat sedikit keuntungan. Ini juga memiliki kelemahan spesifik dari metode yang tidak peduli tentang mutabilitas (misalnya saya hanya ingin mengulang daftar) sekarang harus mendukung dua antarmuka yang terpisah. Karena Java diketik secara statis, ini berarti metode tambahan untuk menangani kedua hierarki antarmuka.
Kami dapat memiliki satu antarmuka dan memungkinkan implementasi untuk melemparkan pengecualian jika suatu metode tidak berlaku untuk itu. Ini adalah rute yang diambil Jawa, dan itu paling masuk akal. Jumlah antarmuka dijaga agar tetap minimum, dan tidak ada invarian mutabilitas karena antarmuka yang terdokumentasi tidak memberikan jaminan tentang mutabilitas . Jika invarian kekekalan diperlukan, gunakan pembungkus di
Collections
. Jika suatu metode tidak perlu mengubah koleksi, cukup jangan mengubahnya. Kekurangannya adalah metode yang tidak dapat menjamin koleksi tidak akan berubah di utas lain jika disediakan koleksi dari luar, tetapi itu tetap merupakan masalah metode panggilan (atau metode panggilannya).Bacaan terkait: Mengapa Java 8 tidak menyertakan koleksi tidak berubah?
sumber
MutableCollection
?Ini pada dasarnya YAGNI. Semua koleksi konkret di perpustakaan standar bisa berubah, menerapkan atau mewarisi operasi opsional. Mereka tidak peduli tentang koleksi abadi untuk tujuan umum dan begitu pula sebagian besar pengembang Java. Mereka tidak akan membuat hierarki antarmuka keseluruhan hanya untuk koleksi yang tidak dapat diubah, kemudian tidak menyertakan implementasi apa pun.
Di sisi lain, ada beberapa nilai tujuan khusus atau koleksi "virtual" yang bisa sangat berguna sebagai tidak berubah, seperti set kosong , dan nCopies . Juga, ada koleksi abadi pihak ketiga (seperti milik Scala), yang mungkin ingin memanggil kode Java yang ada, sehingga mereka membiarkan kemungkinan koleksi tidak tetap terbuka dengan cara yang paling tidak mengganggu.
sumber