# Ãok Biçimlilik (Polymorphism) Ãok biçimlilik aynı görevin veya iÅin farklı yollarla yapılabilmesini ifade eder. Nesne, aynı davranıÅı farklı formlar ve görünüÅler ile yerine getirebilir. Bunu yapabilmek için iki yöntem vardır. 1. Overriding in Java (Ezme) 2. Overloading in Java (AÅırı yükleme) ## AÅırı Yükleme (Overloading) ```java public class Sum { // aÅırı yüklenmiÅ sum() fonksiyonu // metod ismi aynı ve 2 parametre alıyor. public static int sum(int x, int y) { return (x + y); } // aÅırı yüklenmiÅ sum() fonksiyonu // metod ismi aynı ve 3 parametre alıyor. public static int sum(int x, int y, int z) { return (x + y + z); } // aÅırı yüklenmiÅ sum() fonksiyonu // metod ismi aynı ve 2 parametre alıyor. Fakat veri tipi int deÄil, double oldu! public static double sum(double x, double y) { return (x + y); } } ``` Yukarıda "Sum" sınıfı içinde "sum" isimli metotlar vardır. Bu metotların hepsi aynı isimle, aynı iÅi yapıyorlar. Fakat, farklı biçimlerle bunu yapıyorlar. Metot ismi aynı olsa da farklı sayıda parametre alıyorlar. Farklı veri tipleri alabiliyorlar. Aynı isimli metodun farklı sayıda parametre veya farklı sayıda veri tipiyle ile çalıÅmasına metot aÅırı yüklenmesi diyoruz. ## Metotların Ezilmesi (Overriding Metods) Java'da alt sınıflar ATA sınıftan aldıkları metotları ezebilirler. Bu yönteme "Overriding" denilmektedir. Alt sınıfta üst sınıfın metodunu ezmek için `@Override` anahtar kelimesi kullanılır. Ãnemli: Metodu ezebilmek için alt sınıftaki metot imzasıyla, üst sınıftaki metot imzası aynı olması gerekmektedir. Metot imzasından kasıt, metot isimlerinin aynı olması, aynı girdileri alması ve aynı tipte deÄer döndürmeli veya döndürmemelidir. Ayrıca, Java'da üst sınıftaki "private" metotları ezemezseniz, yani "override" edemezsiniz. ```java @Override protected void showInfo() { System.out.println("ElectricCar: " + toString()); } ``` Yukarıdaki "showInfo" metodu, "ElectricCar" sınıfı içinde `@Override` tanımlamasıyla üst sınıftaki metodu ezmektedir. "ElectricCar" tipinden oluÅturulan nesneler üzerinden "showInfo" metodunu çaÄıracak olursak "ElectricCar" sınıfı içindeki metodu çaÄıracaktır. ```java ElectricCar electricCar3 = new ElectricCar(); electricCar3.setLicensePlate("45 FB 1907"); electricCar3.setBrand("BMW"); /* ElectricCar tipinde bir nesne yaratıp, bu nesne üzerinden "showInfo" metodunu çaÄırdıÄımızda, * "ElectricCar" sınıfı içindeki metodu çaÄıracaktır. * Metot ezmesi yaptıÄımız için kalıtım aldıÄı üst sınıftaki "Car" sınıfındaki "showInfo" metodunu çaÄırmayacaktır. */ electricCar3.showInfo(); ``` ```java Ekran Ãıktısı: ElectricCar: [BMW 45 FB 1907 1000.0] ``` "Car" sınıfı tipinden üretilmiÅ olan nesne üzerinden "showInfo" metodu çaÄırıldıÄında alt sınıftakileri deÄil de "Car" sınıfında tanımlı olan metodu çaÄıracaktır. ```java Car carObject1 = new Car(); carObject1.setBrand("Mercedes"); carObject1.setLicensePlate("34 AKH 1970"); /* Car tipinde bir nesne yaratıp, bu nesne üzerinden "showInfo" metodunu çaÄırdıÄımızda, * "Car" sınıfı içindeki metodu çaÄıracaktır. Alt sınıftaki sınıflara ait metotları çaÄırmayacaktır. */ carObject1.showInfo(); ``` ```java Ekran Ãıktısı: Car: [Mercedes 34 AKH 1970] ``` ### Polymorphism Ãzellikleri * PolyMorphism: Bir nesnenin birden fazla nesne gibi davranması olarak tanımlanabilir. * Bir tane superclass'a ihtiyaç vardır. Superclass'ı inheritance yoluyla miras alan subclasslar olmalı. * Superclass'dan türetilen referans deÄeri new ile subclass adıyla da çaÄırılır. * EÄer subclass içinde overriding yapılmıÅsa subclass içindeki metod superclass içindeki metodu ezer. * Sonuç olarak Hayvan sınıfı farklı hayvan sınıflarına göre farklı davranıÅlar gösterdi. * Bir fonksiyona farklı nesneler göndermek isterseniz polymorphism iÅe yarayacaktır. * Superclass nesnesini default parametre olarak verirseniz onu miras almıŠdiÄer nesneler * fonksiyon içinde çaÄırıldıÄında Hayvan sınıfı artık subclass gibi davranır. * Tip dönüÅümü yapmadan parametre olarak farklı deÄerleri yazdırabiliyoruz. #### Ãrnek: ```java package org.java.review.oop; class Hayvan{ private String isim; public Hayvan(String isim) { this.isim = isim; } public String getIsim() { return isim; } public void setIsim(String isim) { this.isim = isim; } public String konus(){ return "Hayvan KonuÅuyor..."; } } class Kedi extends Hayvan{ public Kedi(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " Miyavlıyor..."; } } class Kopek extends Hayvan { public Kopek(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " Havlıyor..."; } } class At extends Hayvan { public At(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " KiÅniyor..."; } } public class Main { public static void konustur(Hayvan hayvan){ System.out.println(hayvan.konus()); } public static void main(String[] args){ // İlk Gösterim Hayvan hayvan = new Hayvan("Hiper"); System.out.println(hayvan.konus()); Hayvan hayvan1 = new Kedi("Hiper"); System.out.println(hayvan1.konus()); Hayvan hayvan2 = new Kopek("Hiper"); System.out.println(hayvan2.konus()); Hayvan hayvan3 = new At("Hiper"); System.out.println(hayvan3.konus()); //Fonksiyon kullanarak gösterim konustur(new Kedi("Nasip")); konustur(new Kopek("KarabaÅ")); konustur(new At("Bold-Pilot")); } } ``` ### instanceof - polymorphism iliÅkisi - Obje vereceÄiz objenin hangi sınıftan olduÄuna bakacaÄız - Kedi sınıfı aynı zamanda Hayvan sınıfından miras alıyor. Bu yüzden superclass'la kıyaslanırsa inheritance olduÄu için true döner. - **_Bütün classlar objeden türüyor.(Object class)_** - Polymorphism kullanmazsak bütün nesneleri instanceof ile kontrol etmemiz gerekir. - **_Yeni bir sınıf üretirsek_** ve Hayvan sınıfından miras alırsa yine kontrol etmemiz gerekecek ama polymorphism bu iÅ yükünü azaltıyor. #### Ãrnek II: ```java package org.java.review.oop; class Hayvan{ private String isim; public Hayvan(String isim) { this.isim = isim; } public String getIsim() { return isim; } public void setIsim(String isim) { this.isim = isim; } public String konus(){ return "Hayvan KonuÅuyor..."; } } class Kedi extends Hayvan{ public Kedi(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " Miyavlıyor..."; } } class Kopek extends Hayvan { public Kopek(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " Havlıyor..."; } } class At extends Hayvan { public At(String isim) { super(isim); } @Override public String konus() { return this.getIsim() + " KiÅniyor..."; } } public class Main { public static void konustur(Object object){ if (object instanceof Kopek){ Kopek kopekTest = (Kopek)object; System.out.println(kopekTest.konus()); } else if(object instanceof Kedi){ Kedi kediTest = (Kedi)object; System.out.println(kediTest.konus()); } else if (object instanceof At){ At atTest = (At)object; System.out.println(atTest.konus()); } else if (object instanceof Hayvan){ Hayvan hayvanTest = (Hayvan)object; System.out.println(hayvanTest.konus()); } } public static void main(String[] args){ // Temel Gösterim Kedi kedi = new Kedi("Nasip"); if (kedi instanceof Kedi){ System.out.println("Bu nesne Kedi sınıfından"); } if (kedi instanceof Hayvan){ System.out.println("Bu nesne Hayvan sınıfından"); } //Fonksiyon ile gösterim Kedi kedii = new Kedi("Nasip"); Kopek kopek = new Kopek("Zizu"); At at = new At("BoldPilot"); Hayvan hayvan = new Hayvan("Turunç"); konustur(kedii); konustur(kopek); konustur(at); konustur(hayvan); } } ``` - Yukarıdaki Ãrnek II Polymorphism'in gerçek faydasını tam olarak ortaya çıkartıyor. Daha fazla hata yapma ihitmali, daha fazla kod ve daha fazla manuel kontrol. Sonuç olarak, polymorphism kullanmak kod temizliÄi ve güvenliÄi açısından verimli bir özellik. ### Kaynaklar - [Oracle - JavaSE Polymorphism](https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) - [Udemy - Online Kurs](https://www.udemy.com/course/sifirdan-ileri-seviyeye-komple-java-gelistirici-kursu/) - [Medium - Nesneye Yönelik Programlama](https://medium.com/s%C4%B1f%C4%B1rdan-i%CC%87leri-d%C3%BCzeye-java-e%C4%9Fitim-serisi/nesneye-y%C3%B6nelik-programlama-oop-be3094786889)