ProgramlamaBackend geliştirici

Yöntem çözüm sırası (method resolution order) Java'da kalıtım sırasında nasıl çalışır ve hangi gizli tuzaklar ortaya çıkabilir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Java'da yöntemlerin aşırı yüklenmesi (overloading) ve yeniden tanımlanması (overriding) belirli kurallara göre gerçekleşir. Aşırı yüklemede (overloading) derleyici, çağrıda bulunan argümanların türüne göre derleme aşamasında en uygun metodu seçer.

Önemli noktalar:

  • Tüm sınıflarda ve üst sınıflarda aşırı yüklenmiş yöntemler varsa, önce mevcut sınıfta en yüksek olası eşleşmeler aranır, ardından üst sınıflarda.
  • Yöntem seçimi, çalıştırma aşamasında değil, derleme aşamasında yapılır.
  • Tür dönüşümleri (widening, autoboxing, varargs) gerekiyorsa uygulanır.

Örnek:

class Super { void print(Number n) { System.out.println("Üst Numara"); } } class Sub extends Super { void print(Integer i) { System.out.println("Alt Tam Sayı"); } } ... Sub s = new Sub(); s.print(5); // Alt Tam Sayı s.print(5.0); // Üst Numara

Burada print(Integer) argüman tipi Integer için çağrılacak, ancak Double tipi için üst sınıf metodu çağrılacaktır.

Tuzağı olan soru.

Eğer bir alt sınıfta yöntem yeniden tanımlanmış (override) ve aşırı yüklenmiş (overload) ise, polimorfizmde hangisi çağrılacaktır?

Cevap: Polimorfizmde her zaman yeniden tanımlanmış yöntemler için gerçek nesne türüne göre yöntem versiyonu seçilir (overriding). Aşırı yüklenmiş yöntemler için seçim, referans türüne göre derleme aşamasında yapılır.

class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Tam Sayı"); } @Override void test(Number n) { System.out.println("B:Numara"); } } ... A obj = new B(); obj.test(1); // B:Numara çağrılacak, test(Integer) olmasına rağmen

Konunun inceliklerini bilmemekten kaynaklanan gerçek hata örnekleri.


Hikaye

Bir geliştirici, alt sınıfa bir aşırı yüklenmiş yöntem sürümü ekledi ve bunun tüm alt sınıflarda çağrılacağını bekledi. Üretim ortamında, üst sınıf referansı üzerinden çağrının referans türüne göre yöntem seçimine neden olduğunu anladı ve gerekli mantık çalışmadı.


Hikaye

Büyük bir projede, equals(Object) yöntemini equals(MyClass obj) imzasıyla hatalı bir şekilde aşırı yüklediler ve bunun standart equals'ın yerine geçeceğini düşündüler. HashSet koleksiyonlarında karşılaştırma yapıldığında varsayılan equals(Object) çalıştı ve bu, mantıksal tutarsızlıklara ve veri kayıplarına neden oldu.


Hikaye

Başka bir yöntem sürümü, varargs ile sınıf hiyerarşisine eklendiğinde, diziler için gereken sürümün çağrılacağını düşündü. Ancak, dizi açıkça geçirildiğinde, derleyici yanlış aşırı yüklemeyi seçti ve bu nedenle işlem yanlış gitti, hata uzun süre fark edilmedi.