Java'da polimorfizm kavramını iyi anlayabilmek için öncelikle Kalıtım anlaşılmış olması gerekir, kalıtımı kısaca özetlemek gerekirse bir class, başka bir classtan extends oluyorsa base classın tüm özelliklerini(private olmayan) miras alır + kendi özellikleri olabilir.
Polimorfizmi kavramak için kalıtım dışında en mühim konu Geç bağlamadır. Geç bağlamayı şöyle özetleyebiliriz, Java kodumuzu yazdık, derleyeceğiz sıkıntı yok buraya kadar peki çalışma esnasında ne olacak hangi metot çağrılacak, neler gerçekleşecek bunlar compile anında belli ise erken bağlamadır; ama polimorfizmde compile esnasında ne olacağı belli değildir bu geç bağlamadır. Çalışma anında gerçekleşen tetiklemelere göre program çalışacaktır. Birazdan bunları kod üzerinde daha anlaşılır şekilde izah etmeye çalışacağım.
Java dilinde polimorfizmin anlaşılması için gerekli olan kalıtım bilgisi + late binding dışında diğer konu upcasting(yukarı doğru çevrim) olsa gerek. Biz yavaş yavaş işi koda dökerek oradan anlatmaya çalışalım:)
Örneğimizden yola çıkarsak
class yer
{
public yer()
{
System.out.println("Ben Sadece Bir Yerim");
}
public void goster(){
System.out.println("**yer classındayım şu anda");
}
}
//İLÇE CLASSI
class ilce extends yer
{
public ilce()
{
System.out.println("İlçe Bir Yerdir");
}
@Override
public void goster(){
System.out.println("**ilçe classındayım şu anda");
}
}
Yukarıda iki tane classım var sadece. ilce classı extends olmuş yer classından.
Ben şimdi aşağıda az önce yazdığım iki tane classı(yukarıdaki) kullanarak upcast edeceğim.
public class ulke {
public ulke()
{
System.out.println("Burası Türkiye :)");
}
public static void cagir(yer m)
{
m.goster();
}
public static void main(String[] args) {
yer y1= new yer();
ilce Söke= new ilce();
cagir(y1);
cagir(Söke);// Upcast var!
}
}
Upcast'teki olay tam olarak benim ulke classı içerisinde static bir metodum var ve benden beklediği yer tipinde bir değişken ve ben bu metodu ona ilce tipinde Söke değişkenini göndererek de çağırabildim:)
Burada bir terslik var diyebilirsiniz; ama Java bunu anlıyor. Çünkü kalıtım bilgisinden hatırlayalım kalıtımda önemli olan "is a" ilişkisidir. Java diyorki sen bir static metot yazmışsın ve 'yer' tipinde parametre göndereceksin cagir(Söke); dediğin zaman ben önce 'Söke' değişkeninin tipine bakarım, baktım ki 'ilce' tipinde sonra 'ilce' classına bakarım o da 'yer' 'den extends olmuş o zaman her 'ilce' bir 'yer'dir. "is a" ilişkisi vardır ve sen bu şekilde kullanabilirsin der bize.
Upcasting'de az çok anlaşıldıktan sonra, polimorfizme geçebiliriz kodda.
class yer
{
public yer()
{
System.out.println("Ben Sadece Bir Yerim");
}
public void goster(){
System.out.println("**yer classındayım şu anda");
}
}
//İLÇE CLASSI
class ilce extends yer
{
public ilce()
{
System.out.println("İlçe Bir Yerdir");
}
@Override
public void goster(){
System.out.println("**ilçe classındayım şu anda");
}
}
public class ulke {
public ulke()
{
System.out.println("Burası Türkiye :)");
}
public static void cagir(yer m)
{
m.goster(); -------polimorfizm burdadır.
}
public static void main(String[] args) {
yer y1= new yer();
ilce Söke= new ilce();
cagir(y1);
cagir(Söke);// Upcast var!
}
}
Biz static cagir metodumuz içerisinden gelen parametreye göre goster metodunu çağırıyoruz; ama burada cagir(Söke) dediğimiz zaman çalışan goster() ile cagir(y1) dediğimiz çalışan goster aynı değildir.
Java bu metot içerisinde m.goster() dediğimiz zaman parametre olarak gelen m değişkeninin heap bölgesinde hangi classa bağlandığına bakar ve ondan sonra o classa ait olan goster metodunu çağırır.cagir(Söke) dediğimizde Söke değişkeni, ilce Söke= new ilce(); kodu ile heap bölgesinde ilce classına bağlanmıştır!
Aşağıda kodu genişleteceğiz. Aşağıdaki kodda komposizyon + kalıtım + override ve polimorfizm vardır. Burada önceden diğerleri biliniyor varsayılıp polimorfizm ve onla ilgili konulara değineceğiz.
*********************************************************
//BASE CLAsS
class yer
{
public yer()
{
System.out.println("Burası Yer Classı");
}
public void goster(){
System.out.println("**yer classındayım şu anda");
}
}
//İLÇE CLASSI
class ilce extends yer
{
public ilce()
{
System.out.println("İlçe Bir Yerdir");
}
@Override
public void goster(){
System.out.println("**ilçe classındayım şu anda");
}
}
//İL CLASSI
class il extends yer
{
public il()
{
System.out.println("İl Bir Yerdir");
}
@Override
public final void goster(){
System.out.println("**il classındayım şu anda");
}
}
//BÜYÜKŞEHİR
class buyuksehir extends il
{
public buyuksehir()
{
System.out.println("Bir İlde Büyükşehir Var");
obj_il.goster();
}
il obj_il=new il();
}
//NORMAL İL
class normalİl extends il
{
public normalİl()
{
System.out.println("Bu İlde Normal Belediye Var");
obj_il.goster();
}
il obj_il=new il();
}
//KASABA CLASSI
class kasaba extends yer
{
public kasaba()
{
System.out.println("Kasaba Bir Yerdir");
}
@Override
public void goster(){
System.out.println("**kasabaya geldim");
}
}
//KÖY CLASSII
class koy extends yer
{
public koy()
{
System.out.println("Köy Bir Yerdir");
}
@Override
public final void goster(){
System.out.println("**köy classındayım şu anda");
}
}
//Köyden BELEDİYE CLASSI
class belediye extends koy
{
public belediye()
{
System.out.println("Köydeki bir belediye...");
koy obj_koy=new koy();
obj_koy.goster();
}
}
//Köyden MUHTARLIK
class muhtarlik extends koy
{
public muhtarlik()
{
System.out.println("Köydeki Bir muhtar");
koy obj_koy=new koy();
obj_koy.goster();
}
}
//BÖLGE CLASSI
class bolge extends yer
{
public bolge()
{
System.out.println("Bölge Oldum...");
}
public bolge(String s)
{
System.out.println("Bu Bölge" +s +"Bölgesidir");
}
public void goster(){
System.out.println("**Bölge classındayım şu anda");
}
muhtarlik m=new muhtarlik();
belediye b=new belediye();
buyuksehir bs=new buyuksehir();
normalİl ni=new normalİl();
//Komposizyon kullandık yukarıda.
}
public class ulke {
public ulke()
{
System.out.println("Burası Türkiye :)");
}
static void cagir(yer y)
{
y.goster();
}
public static void main(String[] args) {
ulke b=new ulke();
yer y1= new yer();
kasaba k1= new kasaba();
koy koy1= new koy();
il i1= new il();
ilce ilce1= new ilce();
bolge karadeniz=new bolge(" Karadeniz ");
cagir(y1);//upcasting yok
cagir(k1);//Upcast var
cagir(koy1);//Upcast var
cagir(i1);//Upcast var
cagir(ilce1);//Upcast var
/*cagir metodu bizden yer tipinde parametre bekliyor; ama biz ona yerden türeyen
diğer değişkenlerimizi de gönderebiliyoruz
Java bunu anlıyor, değişkene bakıyor ve heap bölgesinde nereye bağlanılmışsa oradan hareketle
bağlanan classın ilgili metodunu çağırıyor.*/
}
}
Polimorfizm sayesinde biz sadece ilgili değişkenimizi hangi metodu çağırmak istiyorsak heap bölgesinde ona bağladık ve gerisini Java halletti. Diğer türlü olsaydı, bilmeseydik polimorfizmi nasıl hallederdik?
Klasik yöntemlerle gelen parametreye bakıp if else'e sokarak istediğimiz metoda gönderirdik.Tek satır kod yerine belkide onlarca satır kod yazacaktık.Ki düşen performans da kod hamballığının dışında işin cabası :/
Kolay Gelsin.