Nesneler arasında fark yoktur; Eğer bir var HashMap<String, Object>
her iki durumda da. Arayüzde nesneye sahip olduğunuz bir fark var. İlk durumda, arayüz ise HashMap<String, Object>
ikinci sırada Map<String, Object>
. Ancak altta yatan nesne aynı.
Kullanmanın avantajı Map<String, Object>
, altta yatan nesneyi, onu kullanan herhangi bir kodla sözleşmenizi bozmadan farklı türde bir harita olarak değiştirebilmenizdir. Bunu beyan ederseniz HashMap<String, Object>
, temeldeki uygulamayı değiştirmek istiyorsanız sözleşmenizi değiştirmeniz gerekir.
Örnek: Diyelim ki bu sınıfı yazıyorum:
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...
}
Sınıf, alt sınıflarla paylaştığı (erişimci yöntemleri aracılığıyla) dize-> nesnesinin birkaç dahili haritasına sahiptir. Diyelim ki HashMap
başlamak için s ile yazıyorum çünkü sınıf yazarken bu uygun yapı olduğunu düşünüyorum.
Daha sonra, Mary kodun alt sınıfını yazar. Her ikisiyle de yapması gereken bir şey var things
ve moreThings
doğal olarak bunu ortak bir yöntemle koyuyor ve yöntemini tanımlarken getThings
/ kullandığım aynı türü kullanıyor getMoreThings
:
class SpecialFoo extends Foo {
private void doSomething(HashMap<String, Object> t) {
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
// ...more...
}
Daha sonra ben kullanırsanız aslında, daha iyi olduğuna karar TreeMap
yerine HashMap
de Foo
. Ben güncelleme Foo
, değişen HashMap
için TreeMap
. Şimdi, SpecialFoo
artık derlemiyor, çünkü sözleşmeyi çiğnedim: s Foo
sağladığını söylerdim HashMap
, ama şimdi TreeMaps
yerine veriyor . Bu yüzden SpecialFoo
şimdi düzeltmeliyiz (ve bu tür bir şey bir kod tabanından dalgalanabilir).
Uygulamamın bir HashMap
(ve bu olduğu) kullandığını paylaşmak için gerçekten iyi bir nedenim olmadıkça , yapmam gereken şey beyan etmekti getThings
ve bundan daha spesifik olmadan getMoreThings
geri dönmekti Map<String, Object>
. Aslında, hatta içinde, başka bir şey yapmak için iyi bir neden engelleme Foo
Muhtemelen ilan etmeli things
ve moreThings
olarak Map
değil, 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...
}
Şimdi Map<String, Object>
yapabildiğim her yerde nasıl kullandığımı , yalnızca gerçek nesneleri oluşturduğumda özel olduğumu unutmayın.
Bunu yapsaydım, Mary bunu yapardı:
class SpecialFoo extends Foo {
private void doSomething(Map<String, Object> t) { // <== Changed
// ...
}
public void whatever() {
this.doSomething(this.getThings());
this.doSomething(this.getMoreThings());
}
}
... ve değişen Foo
olmazdı SpecialFoo
durdurma derleme.
Arayüzler (ve temel sınıflar) , gerekli olduğu kadar değişiklik yapmak için esnekliğimizi kapakların altında tutarak , sadece gerektiği kadar açığa çıkarmamıza izin verir . Genel olarak, referanslarımızın mümkün olduğunca temel olmasını istiyoruz. Bunun a olduğunu bilmemize gerek yoksa HashMap
, sadece a deyin Map
.
Bu kör bir kural değildir, ancak genel olarak, en genel arayüze kodlama daha spesifik bir şeyi kodlamaktan daha az kırılgan olacaktır. Bunu hatırlasaydım, Foo
Mary'yi başarısızlık için ayarlayan bir şey yaratmazdım SpecialFoo
. Eğer Mary o zaman berbat halde olduğunu hatırlamıştı Foo
, o ile onun özel yöntem ilan olurdu Map
yerine HashMap
ve benim değişen Foo
'ın sözleşmesini onun kodunu etkiledi olmazdı.
Bazen bunu yapamazsın, bazen spesifik olmalısın. Ancak olmanız için bir nedeniniz yoksa, en az spesifik arayüze yöneliniz.