Tidak ada perbedaan antara objek; Anda memiliki HashMap<String, Object>
dalam kedua kasus. Ada perbedaan dalam antarmuka yang Anda miliki ke objek. Dalam kasus pertama, antarmuka adalah HashMap<String, Object>
, sedangkan yang kedua adalah Map<String, Object>
. Tetapi objek yang mendasarinya adalah sama.
Keuntungan menggunakan Map<String, Object>
adalah Anda dapat mengubah objek yang mendasarinya menjadi jenis peta yang berbeda tanpa memutus kontrak Anda dengan kode apa pun yang menggunakannya. Jika Anda menyatakannya sebagai HashMap<String, Object>
, Anda harus mengubah kontrak Anda jika Anda ingin mengubah implementasi yang mendasarinya.
Contoh: Katakanlah saya menulis kelas ini:
class Foo {
private HashMap<String, Object> things;
private HashMap<String, Object> moreThings;
protected HashMap<String, Object> getThings() {
return this.things;
}
protected HashMap<String, Object> getMoreThings() {
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
Kelas memiliki beberapa peta internal objek string-> yang dibagikan (melalui metode accessor) dengan subclass. Katakanlah saya menulisnya dengan HashMap
s karena saya pikir itu adalah struktur yang tepat untuk digunakan ketika menulis kelas.
Kemudian, Mary menulis kode subkelasnya. Dia memiliki sesuatu yang perlu dia lakukan dengan keduanya things
dan moreThings
, jadi secara alami dia menempatkan itu dalam metode umum, dan dia menggunakan tipe yang sama yang saya gunakan pada getThings
/ getMoreThings
ketika mendefinisikan metodenya:
class SpecialFoo extends Foo {
private void doSomething(HashMap<String, Object> t) {
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
// ...more...
}
Kemudian, saya memutuskan bahwa sebenarnya, lebih baik jika saya menggunakan TreeMap
daripada HashMap
di Foo
. Saya memperbarui Foo
, berubah HashMap
menjadi TreeMap
. Sekarang, SpecialFoo
tidak mengkompilasi lagi, karena saya telah melanggar kontrak: Foo
dulu mengatakan itu diberikan HashMap
, tetapi sekarang menyediakan itu TreeMaps
sebagai gantinya. Jadi kita harus memperbaikinya SpecialFoo
sekarang (dan hal semacam ini dapat mengacak basis kode).
Kecuali saya memiliki alasan yang sangat bagus untuk berbagi bahwa implementasi saya menggunakan HashMap
(dan itu memang terjadi), apa yang seharusnya saya lakukan adalah menyatakan getThings
dan getMoreThings
hanya kembali Map<String, Object>
tanpa menjadi lebih spesifik dari itu. Bahkan, kecuali alasan yang baik untuk melakukan sesuatu yang lain, bahkan di dalam Foo
saya mungkin harus menyatakan things
dan moreThings
sebagai Map
, bukan HashMap
/ TreeMap
:
class Foo {
private Map<String, Object> things; // <== Changed
private Map<String, Object> moreThings; // <== Changed
protected Map<String, Object> getThings() { // <== Changed
return this.things;
}
protected Map<String, Object> getMoreThings() { // <== Changed
return this.moreThings;
}
public Foo() {
this.things = new HashMap<String, Object>();
this.moreThings = new HashMap<String, Object>();
}
// ...more...
}
Perhatikan bagaimana saya sekarang menggunakan di Map<String, Object>
mana saja saya bisa, hanya spesifik ketika saya membuat objek yang sebenarnya.
Jika saya melakukan itu, maka Mary akan melakukan ini:
class SpecialFoo extends Foo {
private void doSomething(Map<String, Object> t) { // <== Changed
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
}
... dan mengubah Foo
tidak akan membuat SpecialFoo
kompilasi berhenti.
Antarmuka (dan kelas dasar) memungkinkan kami mengungkapkan sebanyak yang diperlukan , menjaga fleksibilitas kami di bawah penutup untuk membuat perubahan yang sesuai. Secara umum, kami ingin agar referensi kami sedasar mungkin. Jika kita tidak perlu tahu itu adalah HashMap
, sebut saja a Map
.
Ini bukan aturan buta, tetapi secara umum, pengkodean ke antarmuka paling umum akan menjadi kurang rapuh daripada pengkodean untuk sesuatu yang lebih spesifik. Jika saya ingat itu, saya tidak akan membuat Foo
yang membuat Mary gagal SpecialFoo
. Jika Mary ingat itu, maka meskipun aku mengacau Foo
, dia akan mendeklarasikan metode pribadinya Map
sebagai ganti HashMap
dan dan Foo
kontrakku yang berubah tidak akan memengaruhi kode etiknya.
Terkadang Anda tidak bisa melakukan itu, terkadang Anda harus spesifik. Tetapi kecuali Anda memiliki alasan untuk itu, berbuat salah menuju antarmuka yang paling tidak spesifik.