Java Polymorphism//PigGunner

ratio

Kıdemli Üye
6 Tem 2013
2,456
6
Turk
Java Polymorphism (Çok Biçimlilik)

Java’da Polymorphism yani çok biçimlilik, bir nesnenin birden fazla nesne gibi davranabilmesidir. Biraz daha açacak olursak farklı şekilde çalışan nesnelere aynı şekilde erişmek de diyebiliriz.

Polymorphism başlığı altında incelememiz gerekn birkaç olay var sırasıyla gidelim.

1- COERCION

Zorlama ve baskılama manalarına gelen coercion, bir tip objenin sorun çıkarmadan başka bir tip objeye dönüşebilmesidir. Bununla ilgili en basit örnekleri casting olabilir. Örneğin; int tipindeki 20 sayısının double tipine dönüştürülüp 42.0 olması bir ‘coercion’ örneğidir.

Peki Polymorphism ile Ne Alakası Var?

Konunun ilerisinde daha detaylı anlayacağız örnekler ile ama şimdilik, örneğin; parametresi superclass olan bir metot olduğunu düşünelim ve metot çağrılırken bu superclass’ınsubclasslarından birinin parametreye yazıldığını düşünelim. Başka türlerde beklentimiz hata vermesi olacaktır. Ancak polymorphism sayesinde coercion yapılarak hata verilmeden işlem tamamlanıyor.

“Derleyici işlemleri yaparken, subclass türünü superclass türüne dönüştürür ve yapılabilecek işlemleri superclass’ ın özellikleriyle sınırlandırır.”

İnsan ve çalışandan oluşan iki adet sınıf oluşturduk ve sınıflara farklı özellikler ekledik. Test için İnsan objesi ile çalışan bir metot yazdık. Daha sonra test ederken bir çalışan objesi gönderdik ve bildiğimiz gibi çalışan “IS-A" insan”dır” olduğu için javacoercion yapabildi ve çalışan objesini insan objesiymiş gibi çalıştırdı. Ancak burada insan objesinin toString metodu ile sınırlandırıldı ve bazı özellikleri (iş, maaş) çıktıya yazılmadı.
Kod:
[CENTER][LEFT]class İnsan { 


    private String isim; 

    private String soyadı; 

    private String tc; 

    private int yıl; 


    public String getİsim() { 

        return isim; 

    } 


    public **** setName(String isim) { 

        this.isim = isim; 

    } 


    public String getSoyadı() { 

        return soyadı; 

    } 


    public **** setSoyadı(String soyadı) { 

        this.soyadı = soyadı; 

    } 


    public String getTc() { 

        return tc; 

    } 


    public **** setTc(String tc) { 

        this.tc = tc; 

    } 


    public int getYıl() { 

        return yıl; 

    } 


    public **** setYıl(int yıl) { 

        this.yıl = yıl; 

    } 


    @[URL="https://www.turkhackteam.org/member.php?u=277185"]over[/URL]ride 

    public String toString() { 

        return "İnsan{" + 

                "isim='" + isim + '\'' + 

                ", soyadı='" + soyadı + '\'' + 

                ", tc='" + tc + '\'' + 

                ", yıl=" + yıl + 

                '}'; 

    } 

} 


class Çalışan extends İnsan { 


    Çalışan () { 

        super(); 

    } 

    private String iş; 

    private long maaş; 


    public String getİş() { 

        return iş; 

    } 


    public **** setİş(String iş) { 

        this.iş = iş; 

    } 


    public long getMaaş() { 

        return maaş; 

    } 


    public **** setMaaş(long maaş) { 

        this.maaş = maaş; 

    } 


    /* 

    @[URL="https://www.turkhackteam.org/member.php?u=277185"]over[/URL]ride 

    public String toString() { 

        return super.toString() + iş + maaş;  

    } 

    */ 

} 


public class CoercionTest { 


    public static **** main(String[] args) { 

    CoercionTest test = new CoercionTest(); 

        Çalışan çalışan = new Çalışan(); 

        çalışan.setİş("Vehbi"); 

        çalışan.setSoyadı("Akdoğan"); 

        çalışan.setYıl(1990); 

        çalışan.setTc("11111111110"); 

        çalışan.setİş("CEO"); 

        çalışan.setMaaş(100000L); 


        test.İnsanBilgisiniYaz( çalışan); 


    } 


    public **** İnsanBilgisiniYaz (İnsan insan) { 

        System.out.println(insan.toString()); 

    } 

} [/LEFT]
[/CENTER]
Burada neden person sınıfını basmıyor ne yapabiliriz? @Override

Yukarıda bahsettiğim problemi çözmek adına override(üzerine yazma) yapılabilir ve çalışan sınıfı için yeni bir toString metodu yazılabilir. Böylece polymorphism sayesinde insan parametresine alt sınıfı olan çalışan girildiğinde çalışan sınıfının toString metodu çalışacak ve bilgiler çıktı olarak verilecek.

2- OVERLOADING

Overloading’i aynı sınıf içinde yapılan overriding gibi de düşünebiliriz. Overloading olayında paramtre sayıları veya parametre tipleri değişik iken aynı isime sahip methodlar yazılabilir.

Burada constructorlar üzerinden overloading’i göstermek istedim. İnsan sınıfında bir default bir de isim ve yaş parametreli constructor oluşturdum daha sonra main sınıfında iki farklı constructor’ı da kullanarak objeleri ürettik. Aynı işlem farklı metotlar içinde uygulanabilir. Örn: Toplam isimli iki metot oluşturup birinde int değerleri girilip diğerinde float değerleri girilip metotların içinde farklı şeyler yaptırılabilir!
Kod:
[CENTER][LEFT]class İnsan { 

    int yaş; 

    String isim; 


    İnsan() { 


    } 


    // overloading 

    İnsan( String isim, int yaş) { 

        this.isim = isim; 

        this.yaş = yaş; 

    } 


    @[URL="https://www.turkhackteam.org/member.php?u=277185"]over[/URL]ride 

    public String toString() { 

        return "isim: " + isim + " yaş: " + yaş; 

    } 

} 


class Main { 

    public static **** main(String[] args) { 


    İnsan insanDefault = new İnsan(); 

    İnsan insanParametreli = new İnsan( "Ali", 15); 


    System.out.println( insanDefault.toString() ); 

    System.out.println( insanParametreli.toString() ); 

} 


} [/LEFT]
[/CENTER]
3- PARAMETRIC

"Parametrik Polimorfizm", Java'daki "Generics" için kullanılan başka bir terimdir. Fikir basit, belirli bir sınıf tarafından hangi türlerin kullanılacağını belirtiyorsunuz, bunun açık bir örneği java.util paketinin tüm koleksiyonlarında mevcut.

Örneğin İnsan sınıfında bir arrayList oluşturdunuz ve içine alt sınıfı olan ve extends eden Mühendis, Teknisyen, İşçi, Çocuk gönderdiniz ancak hiç birinde sıkıntı yaşamadınız çünkü aslında hepsi birer İnsan.

Özetle; “Super class gönderiyoruz parametre ama sub class yazdığımızda sıkıntı çıkmıyor.”

Burada bu konu ile birazcık bağlantılı UPCASTING ve DOWNCASTING’e de birazcık değinmemiz gerekiyor.

UPCASTING

Teorik olarak bir örnek anlatarak upcasting’i anlatalım. Örneğin İnsan sınıfı parametresi olan bir metodunuz var ancak sizin İşçi isimli İnsan sınıfından türemiş bir sınıfınız daha var. Metodu kullanırken, parametrenin bulunduğu yere işçi sınıfını girdiğimizi varsayalım. Ancak javacompiler sorun çıkartmıyor. Çünkü, burada UPCASTING yapılıyor ve aslında polymorphism’de yapılmış oluyor ve zaten burada bahsettiklerimiz aşırı bağlantılı, işçi nesnemiz insanmış gibi davranarak işçi gibi çalışıyor.

DOWNCASTING

DOWNCASTING’de bu konuda değinmemiz gereken bir konu, yukarıdaki olayın tam tersi ama burada tahmin edebileceğiniz gibi sorunlar var. Örneğin ya girdiğim yer insan sınıfının alt sınıfı değilse, örneğin işçi metodu için insan girdiğimiz de sorun yok ancak ya bağımsız bir Hayvan sınıfı oluşturup onu girdiğimizi düşünürsek. Burada ClassCastException hatası alacağız. Yani cast edemeyeceğimiz bir sınıfı girmiş olacağız. Bu hatayı önlemek için de instanceOfmethodunu kullanacağız.

Burada ClassCastException, alınabilecek bir durum mesela bir metodun içinde Dog nesnesi üreticeksiniz ancak Cat nesnesi girilmiş herhangi bir bağlantısı olmayan sınıflar, instanceof ile kontrol edilip daha sonra nesne üretilirse sorun olmayacaktır.

Veya String objesi intcast edilemez burada da aynı hata alınır. Bu tarz hataların alındığı bir yerde if ile instanceof kontrolü olabilir ya da duruma göre daha kompleks veya basit şeyler yapılabilir. Şu an spesifik ve güzel bir örnek aklıma gelmedi. Instanceof metodunu inceleyelim.

INSTANCEOF ( instanceof )

Basitçe instanceOfmethodunu nesne hangi sınıfa ait anlamak için kullanıyoruz.

Çok biçimlilik olmadığında kullanılır.

Instanceof methodu booleandır yani true ya da false döner.

Ayrıca instanceOfmethodu, Super sınıfın, eğer varsa süper sınıfları içinde ‘true’ dönecektir.

Örn;
Kod:
[CENTER][LEFT]class Hayvan { 

} 


class Köpek extends Hayvan { 

} 


class YavruKöpek extends Köpek { 

} 


class Main { 

public static **** main(String[] args){ 

   YavruKöpek k9 = new YavruKöpek(); 


   System.out.println("k9 bir YavruKöpek mi?: " + (k9 instanceof YavruKöpek)); 

   System.out.println("k9 bir Köpek mı?: " + (k9 instanceof Köpek)); 

   System.out.println("k9 bir Hayvan mı?: " + (k9 instanceof Hayvan)); 

} 

} [/LEFT]
[/CENTER]
WTRA42.png


Gördüğünüz gibi hem kendisi hem üst sınıfı hemde üst sınıfının üst sınıfı instanceof ile true dönebiliyor.

LATE BINDING (GEÇ BAĞLAMA)

En genel tanımıyla çok biçimliliğin oluştuğu anda, yani run time sırasında nesne örneğinin bağlanacağı nesne türünün belirlenmesi ve buna uygun işlemlerin tamamlanması sürecinde yapılan işlemlerdir.

Çok biçimlilik olmadan geç bağlamadan bahsedilemez.

EARLY BINDING (ERKEN BAĞLAMA)

LATE BINDING’de olan durumun tam tersi yani, run time sırasında değil de, compile sırasında nesne örneğinin bağlanacağı nesne türünün ve işlemlerinin tamamlanması.

POLYMORPHISM ŞARTLARI

1- İnsan gibi bir ana sınıfınızın olmalıdır.

2- Geri kalan sınıflar İnsan sınıfının alt sınıfları olacak ve İnsan sınıfından miras alacaklar. Örn: Çalışan Sınıfı

Yani bir objeyi birden fazla obje gibi kullanabiliyoruz. Ancak bunun için inheritance( kalıtım, miras) tipi bir yapınızın olması gerekiyor.

MANTIK OLARAK POLYMORPHISM;

Hayvan parametresine biz sırasıyla hayvan, köpek ve yavru köpeği atıyoruz. Ve yukarıdan başlıyor.

Sırasıyla,

konus() metodum var mı diye bakıyor. Bana atanan bir referans vardı. Onun konus() metodu var mı? Varsa onu yoksa kendi metodunu (yani hayvan.konus() metodunu) çağırıyor.
Kod:
[CENTER][LEFT]class Hayvan { 

    String name; 


    **** Konus() { 

        System.out.println( "HAYVAN konusuyor"); 

    } 

} 


class Köpek extends Hayvan { 

    String name; 


    @[URL="https://www.turkhackteam.org/member.php?u=277185"]over[/URL]ride 

    **** Konus() { 

        System.out.println( "KÖPEK konusuyor"); 

    } 

} 


class YavruKöpek extends Köpek { 

    String name; 


    @[URL="https://www.turkhackteam.org/member.php?u=277185"]over[/URL]ride 

    **** Konus() { 

        System.out.println( "YAVRU_KÖPEK konusuyor"); 

    } 

} 


class Main { 

public static **** main(String[] args){ 

   Hayvan hayvan = new Hayvan(); 

   Köpek köpek = new Köpek(); 

   YavruKöpek yavruKöpek = new YavruKöpek(); 


   hayvan.Konus(); 

   köpek.Konus(); 

   yavruKöpek.Konus(); 

} 


**** Konustur( Hayvan hayvan) { 

     hayvan.Konus(); 

} 

} [/LEFT]
[/CENTER]
AVANTAJ

Bir fonksiyonumuzun ve birden fazla nesnemizin olduğunu düşünelim. Eğer polymorphism yaparsanız bunları aynı fonksiyona herhangi bir tür dönüşümü yapmadan direk olarak gönderebiliyorsunuz.

Kodun kararlılığını, okunabilirliğini ve anlaşılabilirliğini arttırır.

Daha kısa bir kod ile aynı şeyi yapabiliyoruz.

Eğer polymorphism olmasaydı if hayvansa, else if köpekse, else ifyavruKöpekse, diye bir sürü if else statement eklemek zorunda kalacaktık ve kodumuz büyük bir projede ciddi şekilde uzayacaktı.

DEZAVANTAJ

Geç bağlamanın(LATE BINDING) run time sırasında olduğu için, nesneler oluştuğu an harcanan karar verme ve gerekli işlemleri yapmak için harcanan süre ekstra olacaktır.

Ekstra NOT: Başka konularda da belirttiğim gibi aslında java’da ki tüm classlarımız javanın içinde yazılmış hazır bulunan object isimli bir classtan türüyor. Biz herhangi bir türetme ya da inheritance işlemi yapmasak bile java otomatik olarak bir tane objectclassından bu classı türetiyor. Yani objectclassının içinden belli metotları alabiliyoruz ve direk kullanabiliyoruz.

Videolu Anlatım

[ame]https://www.youtube.com/watch?v=CzkNAWRxTZ0[/ame]

Kaynakça

 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.