DÜZENLEME: Bu soruyu cevapladım, çünkü bunu soran programlamayı öğrenen bir sürü insan var ve cevapların çoğu teknik olarak yetkin, ancak bir acemi iseniz anlamak kolay değil. Hepimiz yeniydik, bu yüzden elimi daha acemi dostu bir cevapta deneyeceğim diye düşündüm.
İki ana polimorfizm ve validasyon. Sadece aptal bir veri yapısı olsa bile.
Diyelim ki bu basit sınıfımız var:
public class Bottle {
public int amountOfWaterMl;
public int capacityMl;
}
İçinde ne kadar sıvı olduğunu ve kapasitesinin ne olduğunu tutan çok basit bir sınıf (mililitre cinsinden).
Yaptığımda ne olur:
Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacityMl = 1000;
Bunun çalışmasını beklemezdin, değil mi? Bir tür akıl sağlığı kontrolünün olmasını istiyorsunuz. Daha da kötüsü, maksimum kapasiteyi hiç belirtmezsem ne olur? Ah canım, bir sorunumuz var.
Ama başka bir sorun daha var. Şişeler sadece bir çeşit konteyner olsaydı ne olurdu? Ya kapasiteleri ve miktarları sıvı dolu olan birkaç kabımız olsaydı? Sadece bir arayüz oluşturabilirsek, programımızın geri kalanının bu arayüzü kabul etmesine izin verebilirdik ve şişeler, bidonlar ve her türlü şey birbirinin yerine kullanılabilirdi. Daha iyi olmaz mıydı? Arayüzler yöntem gerektirdiğinden, bu da iyi bir şeydir.
Sonunda şöyle bir şey buluruz:
public interface LiquidContainer {
public int getAmountMl();
public void setAmountMl(int amountMl);
public int getCapacityMl();
}
Harika! Ve şimdi Şişeyi buna değiştiriyoruz:
public class Bottle extends LiquidContainer {
private int capacityMl;
private int amountFilledMl;
public Bottle(int capacityMl, int amountFilledMl) {
this.capacityMl = capacityMl;
this.amountFilledMl = amountFilledMl;
checkNotOverFlow();
}
public int getAmountMl() {
return amountFilledMl;
}
public void setAmountMl(int amountMl) {
this.amountFilled = amountMl;
checkNotOverFlow();
}
public int getCapacityMl() {
return capacityMl;
}
private void checkNotOverFlow() {
if(amountOfWaterMl > capacityMl) {
throw new BottleOverflowException();
}
}
BottleOverflowException tanımını okuyucuya alıştırma olarak bırakacağım.
Şimdi bunun ne kadar daha sağlam olduğuna dikkat edin. Bottle yerine LiquidContainer'ı kabul ederek kodumuzdaki her türlü konteyneri ele alabiliriz. Ve bu şişelerin bu tür şeylerle nasıl başa çıktığı farklı olabilir. Değiştiğinde durumlarını diske yazan şişeleriniz olabilir ya da SQL veritabanlarına veya GNU'ya kaydedilen şişelerin başka neleri bildiğini görebilirsiniz.
Ve tüm bunların çeşitli boğmacalarla başa çıkmanın farklı yolları olabilir. Şişe sadece kontrol eder ve taşarsa bir RuntimeException kurar. Ama bu yanlış bir şey olabilir. (Hata işleme konusunda yararlı bir tartışma var, ancak burada bunu çok basit bir şekilde saklıyorum. Yorumdaki insanlar muhtemelen bu basit yaklaşımın kusurlarını gösterecektir.))
Ve evet, çok basit bir fikirden hızlıca daha iyi cevaplar almaya gittik.
Bir şişenin kapasitesini değiştiremeyeceğinizi lütfen unutmayın. Şimdi taşa konmuş. Bunu son olarak ilan ederek bir int ile yapabilirsiniz. Ancak bu bir liste olsaydı, listeyi boşaltabilir, listeye yeni şeyler ekleyebilir ve böyle devam edebilirsiniz. İç kısımlara dokunmaya erişimi sınırlandıramazsınız.
Herkesin ele almadığı üçüncü şey de var: alıcılar ve ayarlayıcılar yöntem çağrılarını kullanıyor. Bu, diğer her yerde normal yöntemlere benzedikleri anlamına gelir. DTO'lar ve şeyler için garip bir sözdizimine sahip olmak yerine, her yerde aynı şeye sahipsiniz.