post-images/overriding-tostring/cover.jpg

Overriding toString()

Merhaba 😇 Hoşgeldin 🤗 Bu yazıda Effective Java kitabının ikinci ünitesi olan Methods Common to All Objects'in üçüncü maddesi Always override toString'i ele alacağız.

Bu madde de Object sınıfı içerisinde yer alan toString() metodunun nasıl override edileceğini, ne işe yaradığını ve yazarken uyulması gereken kurallar varsa bunları inceleyeceğim.

Geleneği bozmadan Object sınıfımızı bir ziyaret edelim ne varmış bu toString() içerisinde bakayım. Aşağıda görebileceğin gibi toString() metodu override edilmediği durumda göreceğimiz çıktı className + @ + hexadecimalHashCode şeklinde olacaktır.

public String toString() {  
    return getClass().getName() + "@" + Integer.toHexString(hashCode());  
}

Pek çok meslektaşım geliştirme yaparken toString() metodunu kullanmıştır. Seninde daha önce kullandığına eminim. Kullandığın durumda iki farklı gösterime şahit olmussundur. Bunlardan biri içerisinde okunabilir, çağrıldığı nesne içerisinden sana anlamlı bilgi veren hali, diğeri ise tövbeestağfirullah şöyle Object@5cad8086 bir şey. Bu karmaşık görüntü toString() metodu çağrılan sınıfın kendine ait toString() implementasyonu olmadığı, Object sınıfından türetildiğinin bir göstergesidir.

Aslına bakarsanız toString() override edilirken sadece tek bir sözleşme maddesine uymanız gerekiyor. Bu madde de "Okuyan kişi için kısa, okuması kolay ve bilgilendirici olması gerekir" şeklindedir ve devamında "Tüm alt sınıfların bu yöntemi geçersiz kılması önerilir" şeklinde bir öneri mevcuttur. Hiç bir override işlemi yapmadığımız durumda karşımıza çıkan PhoneNumber@5cad8086 metni aslında sözleşme maddesine uymaktadır. Göründüğü gibi kısa, okuması kolay ve bir bilgi veriyor. Ama burda verilen bilgi bizler için pek anlamlı olmuyor. Tam bu aşamada neden toString() override ettiğimizi anlamışsındır.

public class PhoneNumber {
    private int areaCode;
    private int prefix;
    private int lineNumber;

    public PhoneNumber(int areaCode, int prefix, int lineNumber) {
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.lineNumber = lineNumber;
    }
}

PhoneNumber adında telefon numaramımı temsil eden bir sınıfım olsun (Tabii ki gerçek değil aramayın🙃). Bu sınıf içerisinde toString() override edilmediği durumda karşılaşacağım görüntü şu şekildedir:

System.out.println(new PhoneNumber(707, 867, 5309).toString());
# PhoneNumber@adbbd

Gördüğün gibi PhoneNumber@adbbd çıktısı sözleşmeye uyar fakat benim için herhangi bir anlam ifade etmiyor. toString() metodumu daha anlamlı çıktı üretecek şekilde düzenlersem eğer:

@Override  
public String toString()  
{  
    return "PhoneNumber{" +  
            "areaCode=" + areaCode +  
            ", prefix=" + prefix +  
            ", lineNumber=" + lineNumber +  
            '}';  
}

Yeni sonucum aşağıdaki şekilde olacaktır:

System.out.println(new PhoneNumber(707, 867, 5309).toString());

# PhoneNumber{areaCode=707, prefix=867, lineNumber=5309}

PhoneNumber{areaCode=707, prefix=867, lineNumber=5309} veya PhoneNumber@adbbd hangisi daha anlaşılır ve bilgi verici? Buna sen karar ver ben vermeyeyim.

toString() metodunu override etmek zorunlu mu? Sorusu aklına geldiyse aslında zorunlu değil. Uygulaman çalışırken yazmış olduğun nesne log olarak atılıyorsa veya senin oluşturmuş olduğun bu nesne sebebiyle bir hata oluştuysa, her bir nesne Object sınıfından türediği için loglarda PhoneNumber@adbbd şeklinde mesajlar göreceksin. Bir sorun tespit ederken veya uygulama içerisinde ne olup bittiğini incelerken bu değerin içerisinde ne olduğu bilmek sana çok büyük avantaj sağlayacaktır.

toString() metodunu override ederken tüm alanların olması gerekli mi? Sözleşme içerisinde buna da değiniliyor. Senin böyle bir zorunluluğun yok hatta mümkün olduğunca sadece önemli alanları barındırman öneriliyor.

Kapatmadan söyleyeyim pek çok IDE (IntelliJ IDEA ❤️)'de nesnenin toString() metodunu otomatik bir şekilde override edebilmeniz için eklentiler bulunur ve bu eklentiler aracılığıyla istediğin alanı toString() içerisine kolayca ekleyebilirsin .

auf Wiedersehen ✌🏼

JavaEffective JavaMethods Common to All ObjectstoStrıng()OverridingSoftware ContractIntelliJ IDEA