Tek İsim, Birden Fazla Sürüm
Önceki sayfada bir metodun parametrelerinin neyi kabul ettiğini nasıl tanımladığını gördün. Metot aşırı yükleme bunu bir adım öteye taşır: parametre listeleri farklı olduğu sürece birden fazla metoda aynı ismi verebilirsin. Derleyici bunları ayrı metotlar olarak ele alır ve gönderdiğin argümanlara göre doğru olanı seçer.
System.out.println bu sayede bir int, bir String, bir boolean ya da bir double değerini sorunsuzca yazdırabilir: tek bir println yoktur, ismi paylaşan birçok aşırı yükleme vardır. Kastettiğin çağrıyı yazarsın, derleyici de onu uygun sürümle eşleştirir.
Her iki metodun adı da square ama biri int, diğeri double alır. 5 değişmezi bir int olduğundan ilk aşırı yükleme çalışır; 2.5 bir double olduğundan ikincisi çalışır.
Farklı Bir Aşırı Yükleme Sayılmak İçin Ne Gerekir
Aşırı yüklemeler parametre listesinde farklılaşmalıdır; bu da şunlardan en az birini gerektirir:
- farklı bir parametre sayısı,
- farklı parametre türleri ya da
- türlerin farklı bir sırası.
Her çağrının parametre listesi üç join metodundan tam olarak biriyle eşleştiği için hiçbir karışıklık yoktur.
Dönüş Türü Sayılmaz
Yeni başlayanlar için sık görülen bir tuzak: yalnızca dönüş türüne göre aşırı yükleme yapmaya çalışmak. Dönüş türü, derleyicinin kullandığı imzanın parçası değildir, bu yüzden şu derlenmez:
// Derlenmez - aynı isim, aynı parametreler, yalnızca dönüş türü farklı
static int value() { return 1; }
static double value() { return 1.0; } // hata: value() zaten tanımlı
Derleyici bunları birbirinden ayırt edemez, çünkü value() gibi bir çağrı noktasında argümanlardaki hiçbir şey hangisini istediğine dair ipucu vermez. Aşırı yüklemelere farklı dönüş türleri verebilirsin, ama yalnızca parametre listeleri zaten farklıysa.
Java Bir Aşırı Yüklemeyi Nasıl Seçer
Birden fazla aşırı yükleme argümanlarını kabul edebiliyorsa, Java en özgül olanı seçer ve genişletme dönüşümü yerine tam tür eşleşmesini tercih eder. Bir int argümanıyla ne olduğuna bak:
show(7) çağrısı, long ve double de genişletmeden sonra bir 7 tutabilecek olsa da tam olarak int ile eşleşir. Yalnızca tam eşleşen aşırı yükleme kaldırılsaydı derleyici int'i önce long'a, sonra double'a genişletirdi. Bu çözümleme tamamen derleme zamanında, argümanlarının bildirilen türlerine göre kararlaştırılır.
Belirsiz Çağrılara Dikkat Et
Hiçbir aşırı yükleme açıkça en iyi eşleşme değilse, derleyici tahmin yürütmeyi reddeder ve bir hata bildirir. Bu en çok, herhangi bir referans türüne uyan null ile yaşanır:
static void handle(String s) { }
static void handle(StringBuilder b) { }
handle(null); // hata: handle referansı belirsiz
Her iki aşırı yükleme de null kabul eder ve hiçbiri daha özgül değildir, bu yüzden çağrı derlenmez. Türü bir cast ile açık hale getirerek - handle((String) null) - ya da aşırı yüklemeler çakışmayacak şekilde yeniden tasarlayarak düzelt. Aynı dikkati autoboxing ile genişletmeyi karıştırırken de göster; aşırı yükleme kümelerini, her çağrının tek bir bariz kazananı olacak kadar basit tut.
Yapıcıları (Constructor) Aşırı Yükleme
Aşırı yükleme yalnızca sıradan metotlarla sınırlı değildir: yapıcılar bunu, bir nesneyi oluşturmanın birden fazla yolunu sunmak için sürekli kullanır. Argümansız bir yapıcı, this(...) ile daha kapsamlı bir yapıcıya iş devredebilir:
İki yapıcı da Point ismini paylaşır ama parametre sayısında farklılaşır, tıpkı aşırı yüklenmiş metotlar gibi. this(...) ile devretmek, ilklendirme mantığını tek bir yerde toplar.
Aşırı Yükleme ile Geçersiz Kılma Karşılaştırması
Bu ikisi kulağa benzer gelir ama birbiriyle ilgisizdir:
- Aşırı yükleme - aynı isim, farklı parametre listeleri, aynı sınıfta. Derleyici sürümü derleme zamanında seçer. Bir işlemin varyantlarını sunmakla ilgilidir.
- Geçersiz kılma - bir alt sınıf, miras aldığı bir metodu aynı isim ve aynı parametrelerle yeniden tanımlar. Java sürümü, nesnenin gerçek türüne göre çalışma zamanında seçer. Davranışı değiştirmekle ilgilidir (kalıtım ve çok biçimlilik konularında karşılaşacaksın).
Parametre listeleri aynıysa geçersiz kılma yapıyorsundur (ya da aynı sınıfta yinelenen metot hatasına yol açıyorsundur); farklıysa aşırı yükleme yapıyorsundur.
Sırada: Varargs
Aşırı yükleme, join(a, b) ve join(a, b, c) metotlarını ayrı metotlar olarak yazmana olanak tanır; ama her sayı için ayrı bir aşırı yükleme tanımlamadan herhangi bir sayıda argüman kabul etmek istersen? Java'nın varargs söz dizimi, tek bir metodun değişken uzunlukta bir argüman listesi almasını sağlar ve bir sonraki sayfanın konusu da budur.
Sıkça Sorulan Sorular
Java'da metot aşırı yükleme nedir?
Metot aşırı yükleme, aynı sınıfta aynı isimli birden fazla metodu, her birini farklı bir parametre listesiyle (farklı parametre sayısı, farklı türler ya da türlerin farklı sırası) tanımlamak demektir. Derleyici, gönderdiğin argümanları her aşırı yüklemenin parametreleriyle eşleştirerek hangi sürümün çağrılacağına karar verir. Bu, çalışma zamanında değil derleme zamanında verilen bir karardır.
Java'da iki metot yalnızca dönüş türüyle farklılaşabilir mi?
Hayır. Dönüş türü, aşırı yükleme açısından bir metodun imzasının parçası değildir; bu yüzden aynı sınıfta int total() ve double total() bir derleme hatasıdır. Aşırı yüklemeler parametre listesinde farklılaşmalıdır: parametrelerin sayısı, türleri veya sırası. Dönüş türü farklı olabilir, ama yalnızca parametrelerdeki bir farkın yanında, tek başına değil.
Java'da aşırı yükleme (overloading) ile geçersiz kılma (overriding) arasındaki fark nedir?
Aşırı yükleme, aynı sınıfta aynı isimli ama farklı parametreli birden fazla metottur ve derleyici tarafından derleme zamanında çözülür. Geçersiz kılma ise bir alt sınıfın, miras aldığı bir metodu aynı isim ve aynı parametrelerle yeniden tanımlamasıdır; nesnenin gerçek türüne göre çalışma zamanında çözülür. Aşırı yükleme varyantlar sunmakla, geçersiz kılma ise davranışı değiştirmekle ilgilidir.