Saya telah mendengar argumen bahwa Anda harus menggunakan antarmuka paling umum yang tersedia sehingga Anda tidak terikat dengan implementasi tertentu dari antarmuka itu. Apakah logika ini berlaku untuk antarmuka seperti java.util.Collection ?
Saya lebih suka melihat sesuatu seperti yang berikut:
List<Foo> getFoos()
atau
Set<Foo> getFoos()
dari pada
Collection<Foo> getFoos()
Dalam kasus terakhir, saya tidak tahu set data apa yang saya hadapi, sedangkan dalam dua contoh pertama saya dapat membuat beberapa asumsi tentang pemesanan dan keunikan. Apakah java.util.Collection memiliki kegunaan di luar menjadi orangtua yang logis untuk kedua set dan daftar?
Jika Anda menemukan kode yang menggunakan Koleksi ketika melakukan peninjauan kode, bagaimana Anda menentukan apakah penggunaannya dibenarkan, dan saran apa yang akan Anda buat untuk penggantiannya dengan antarmuka yang lebih spesifik?
Collection<List<?>>
? Bicara tentang pengkodean horor!Jawaban:
Abstraksi hidup lebih lama dari implementasi
Secara umum, semakin abstrak desain Anda, semakin besar kemungkinan akan berguna. Jadi, karena Koleksi lebih abstrak daripada sub-antarmuka, maka desain API berdasarkan Koleksi lebih cenderung tetap berguna daripada yang didasarkan pada Daftar.
Namun, prinsip menyeluruhnya adalah menggunakan abstraksi yang paling tepat . Jadi jika koleksi Anda harus mendukung elemen yang dipesan maka mandat Daftar, jika tidak ada duplikat maka mandat Set, dan sebagainya.
Catatan tentang desain antarmuka generik
Karena Anda tertarik menggunakan antarmuka Koleksi dengan obat generik, Anda mungkin dapat membantu yang berikut ini. Java Efektif oleh Joshua Bloch merekomendasikan pendekatan berikut saat merancang antarmuka yang akan bergantung pada obat generik: Producers Extend, Consumers Super
Ini juga dikenal sebagai aturan Pecs . Pada dasarnya, jika koleksi umum yang menghasilkan data diteruskan ke kelas Anda, tanda tangan akan terlihat seperti ini:
Jadi tipe inputnya bisa E atau subclass dari E (E didefinisikan sebagai super-dan sub-kelas dari dirinya sendiri dalam bahasa Java).
Sebaliknya, koleksi umum yang diteruskan untuk menggunakan data harus memiliki tanda tangan seperti ini:
Metode ini akan menangani dengan benar superclass dari E. Secara keseluruhan, menggunakan pendekatan ini akan membuat antarmuka Anda kurang mengejutkan bagi pengguna Anda karena Anda akan dapat masuk
Collection<Number>
danCollection<Integer>
memperlakukan mereka dengan benar.sumber
The
Collection
interface, dan bentuk yang paling permisifCollection<?>
, sangat bagus untuk parameter yang Anda terima. Berdasarkan penggunaan di perpustakaan Java itu sendiri lebih umum sebagai tipe parameter daripada tipe kembali.Untuk jenis kembali, saya pikir poin Anda valid: Jika orang diharapkan mengaksesnya, mereka harus mengetahui urutan (dalam arti Big-O) dari operasi yang dilakukan. Saya akan mengulangi pengembalian
Collection
dan menambahkannya ke Koleksi lain, tetapi sepertinya agak gila untuk memanggilnyacontains
, tidak tahu apakah itu operasi O (1), O (log n), atau O (n). Tentu saja, hanya karena Anda memiliki tandaSet
bukan berarti itu hashset atau set yang diurutkan, tetapi pada titik tertentu Anda akan membuat asumsi bahwa antarmuka telah dilaksanakan secara wajar (dan kemudian Anda harus pergi ke rencana B jika asumsi Anda terbukti salah).Seperti yang disebutkan Tom, terkadang Anda perlu mengembalikan a
Collection
untuk mempertahankan enkapsulasi: Anda tidak ingin detail implementasi bocor, bahkan jika Anda bisa mengembalikan sesuatu yang lebih spesifik. Atau, dalam kasus yang disebutkan Tom, Anda bisa mengembalikan wadah yang lebih spesifik, tetapi Anda harus membuatnya.sumber
Saya akan melihatnya dari sudut pandang yang benar-benar berlawanan, dan bertanya:
Sangat mudah untuk membenarkan ini. Anda menggunakan Daftar saat Anda membutuhkan beberapa fungsi yang tidak ditawarkan oleh Koleksi. Jika Anda tidak membutuhkan fungsionalitas ekstra itu - justifikasi apa yang Anda miliki? (Dan saya tidak akan membeli, "Saya lebih suka melihatnya")
Ada banyak kasus di mana Anda akan menggunakan koleksi untuk tujuan hanya-baca, mengisi semuanya sekaligus, mengulangi seluruhnya - apakah Anda perlu mengindeksnya secara manual?
Untuk memberi contoh nyata. Katakanlah saya melakukan permintaan sederhana pada database. (
SELECT id,name,rep FROM people WHERE name LIKE '%squared'
) Saya mengambil kembali data yang relevan, mengisi objek Person dan memasukkannya ke PersonList)Jadi pembenaran apa yang akan saya miliki untuk metode ekstra itu? (yang akan tetap tidak diterapkan di PersonList saya)
sumber