You are on page 1of 15

Polimorfizm, nesneye ynelik programlamann nemli kavramlarndan biridir ve szlk anlam olarak "bir ok ekil" anlamna gelmektedir.

Polimorfizm ile kaltm konusu i iedir. Kaltm konusu bir nceli yazmzda incelenmiti; kaltm konusunda iki taraf bulunmaktadr, ana snf ve bu snftan treyen alt snf/snflar. Alt snf, tretildii ana snfa ait tm zellikleri alr; yani, ana snf ne yapyorsa tretilen alt snfta bu ilemlerin aynsn yapabilir ama tretilen alt snflarn kendilerine ait bir ok yeni zellii de olabilir. Ayrca tretilen alt snfa ait nesnenin, ana snf tipindeki referansa balamann yukar doru (upcasting)ilemi olduu geen blm incelenmiti. Burada anlatlanlar bir rnek zerinde aklarsak;
class Universite { public void dersCalis() { System.out.println("Herkes ders calisti"); } } class Ogrenci extends Universite { public void dersCalis() { System.out.println("Ogrenci ders calisti"); } } class Akademisyen extends Universite{ public void dersCalis() { System.out.println("Akademisyen ders calisti"); } } public class PolimorfizmOrnekBir { public static void hazirlanSinavVar(Universite uni) { uni.hazirlanSinavVar(); // ! Dikkat ! } public static void main(String args[]) { Universite uni = new Universite(); Ogrenci ogr = new Ogrenci(); Akademisyen ogrGor = new Akademisyen(); hazirlanSinavVar(uni); // yukar cevirim ! yok ! hazirlanSinavVar(ogr); // yukar cevirim (upcasting) hazirlanSinavVar(ogrGor); // yukar cevirim (upcasting) } }

Yukardaki rnekte kavram mevcuttur, bunlardan biri yukar evirim (upcasting) dieri polimorfizm ve son olarak da ge balama (late binding). imdi yukar evirim ve polimorfizm kavramlarn aklayalm. Bu rneimizde ana snf Universite snfdr; bu snfdan treyen snflar ise Ogrenci ve Akademisyen snflardr. Bu iliki "bir" ilikisidir ; Ogrenci bir Universitelidir, veya Akademisyende bir Universitelidir, diyebiliriz. Yani Universite snfnn yapt her ii Ogrenci snf veya Akademisyen snf da yapabilir art tretilen bu iki snf kendisine has zellikler tayabilir, Universite snf ile Ogrenci ve Akademisyen snflarnn arasnda kaltmsal bir iliki bulunmasndan dolay, Universite tipinde parametre kabul eden hazirlanSinavVar() yordamna Ogrenci ve Akademiyen tipindeki referanslar paslayabildik, bu zelliinde yukar evirim (upcasting) olduunu bir nceki yazmzda incelemitik. Polimorfizm ise hazirlanSinavVar() yordamnn ierisinde gizlidir. Bu yordamn (method) ierisinde Universite tipinde olan uni referans kendisine gelen 2 deiik nesneye (Ogrenci ve Akademisyen) balanabildi; bunlardan biri Ogrenci dieri ise Akademisyendr. Peki bu yordamn ierisinde neler olmaktadr? Sras ile aklarsak; ilk nce Universite nesnesine bal Universite tipindeki referans,hazirlanSinavVar() yordamna parametre olarak gnderiyoruz, burada herhangi bir terslik yoktur nk hazirlanSinavVar() yordam zatenUniversite tipinde parametre kabul etmektedir. Burada dikkat edilmesi gereken husus, hazirlanSinavVar() yordamnn ierisinde Universite tipindeki yerel uni deikenimizin, kendi tipinden baka nesnelere de (Er ve Akademisyen) balanabilmesidir; yani, Universite tipindeki yerel uni deikeni bir ok ekle girmi bulunmaktadr. Aadaki ifadelerin hepsi dorudur: Universite a = new Universite() ; Universite a = new Er(); Universite a = new Akademisyen(); Yukardaki ifadelere, Universite tipindeki uni deikenin asndan bakarsak, bu deikenin bir ok nesneye balanabildiini grrz, bu zellik polimorfizm dir ki bu zelliin temelinde kaltm (inheritance) yatar. imdi sra ge balama (late binding) zelliinin aklanmasnda.... Ge Balama (Late Binding)

hazirlanSinavVar(ogr); // yukari dogru cevirim (upcasting)

class Hayvan { public void avYakala() { System.out.println("Hayvan avYakala"); } } class Kartal extends Hayvan { public void avYakala() { System.out.println("Kartal avYakala"); } } class Timsah extends Hayvan{ public void avYakala() { System.out.println("Timsah avYakala"); } } public class PolimorfizmOrnekIki { public static Hayvan rasgeleSec() { int sec = ( (int) (Math.random() *3) ) ; Hayvan h = null ; if (sec == 0) h = new Hayvan(); if (sec == 1) h = new Kartal(); if (sec == 2) h = new Timsah(); return h; } public static void main(String args[]) { Hayvan[] h = new Hayvan[3]; // diziyi doldur for (int i = 0 ; i < 3 ; i++) { h[i] = rasgeleSec(); //upcasting } // dizi elemanlarini ekrana bas for (int j = 0 ; j < 3 ; j++) { h[j].avYakala(); // !Dikkat! } } }

Yukardaki rnekte bulunan kaltm (inheritance) ilikisini, UML diyagramnda gsterirsek:

PolimorfizmOrnekIki.java rneimizde rasgeleSec() yordam, rasgele Hayvan nesneleri oluturup geri dndrmektedir. Geri dndrlen bu Hayvannesneleri, Hayvan tipindeki dizi ierisine atlmaktadr. Hayvandizisine atlan Kartal ve Timsah nesnelerine Javann kzmamasndaki sebep kaltmdr. Kartal bir Hayvandr diyebiliyoruz ayn ekilde Timsah bir Hayvandr diyebiliyoruz; olaylara bu adan bakarsak Hayvan tipindeki dizi ierisine eleman atarken yukar evirim (upcasting) olduunu fark edilir. Ge balama ise, Hayvan dizisinin ierisindeki elemanlara ait avYakala() yordamn arrken karmza kar. Buradaki ilgin nokta hangi nesnenin avYakala() yordamnn arlacann derleme annda (compile-time) bilinemiyor olmasdr. Nasl yani diyenler iin konuyu biraz daha

aalm. rasgeleSec() yordamn incelersek, Math.random() yordamnn her seferinde 0 ile 2 arasnda rasgele saylar rettii grlr. Bu retilen saylar dorultusunda Hayvan nesnesi Kartal nesnesi veya Timsah nesnesi dndrlebilir; bu sebepten dolay uygulamamz her altrdmzda Hayvan tipindeki dizinin ierisine deiik tipteki nesnelerin, deiik srada olabilecekleri grlr. rnein PolimorfizmIki uygulamamz kere st ste altrp kan sonular inceleyelim; Uygulamann kts aadaki gibidir; Kartal avYakala Hayvan avYakala Kartal avYakala Ayn uygulamamz tekrardan altrdmz zaman yeni kt; Timsah avYakala Timsah avYakala Hayvan avYakala Tekrar altryoruz; Timsah avYakala Hayvan avYakala Kartal avYakala Grld zere dizi ierisindeki elemanlar her sefersinde farkl olabilmektedir, dizi ierisindeki elemanlar ancak alma annda (runtime) belli oluyorlar. h[j].avYakala() derken, derleme annda (compile-time) hangi nesnenin avYakala() yordamnn arlacan Java tarafndan bilinemez, bu olay ancak alma annda (run-time) bilinebilir. Ge balama zellii bu noktada karmza kar. Ge balamann (late-binding) dier isimleri, dinamik balama (dynamic-binding) veya alma annda balamadr (runtime-binding). Final ve Ge Balama Bir nceki yazmzda ( snflarn tekrar kullanlmas ), final zelliinin kullanlmasnn iki sebebi olabileceini belirtmitik. Bunlardan bir tanesi tasarm dieri ise verimliliktir. Verimlilik konusu ge balama (late binding) zellii ile aydnlam bulunmaktadr, yle ki, eer biz bir snf final yaparsak, bu snfa ait tm yordamlar final yapm oluruz veya eer istersek tek bana bir yordam da final yapabiliriz. Bir yordam final yaparak unu demi oluruz, bu yordam, tretilmi olan alt snflarn ierisindeki dier yordamlar tarafndan iptal edilemesin(override) Eer bir yordam iptal edilemezse o zaman ge balama (late binding) zellii de ortadan kalkar. Uygulama ierisinde herhangi bir nesneye ait normal bir yordam (final olmayan) arldnda, Java, acaba doru nesnenin uygun yordam mu arlyor diye bir kontrol yapar, daha dorusu ge balamaya (late-binding) ihtiya var m kontrol yaplr. rnein Kedi snfn gz nne alalm. Kedi snf final olmadndan dolay bu snftan tretilme yapabiliriz. KediKaplan.java
class Kedi { public void yakalaAv() { System.out.println("Kedi sinifi Av yakaladi"); } } class Kaplan extends Kedi { public static void goster(Kedi k) { k.yakalaAv(); } public void yakalaAv() { System.out.println("Kaplan sinifi Av yakaladi"); } public static void main(String args[] ) { Kedi k = new Kedi() ; Kaplan kp = new Kaplan(); goster(k); goster(kp); // yukari dogru cevirim (upcasting) } }

Kaplan snfna ait statik bir yordam olan goster() yordamnn ierisinde Kedi tipindeki k yerel deikene bal olan nesnenin, yakalaAv()yordam arlmaktadr ama hangi nesnenin yakalaAv() yordam? Kedi nesnesine ait olan m? Yoksa Kaplan nesnesine ait olan m? Java,yakalaAv() yordamn armadan nce ge balama (late-binding) zelliini devreye sokarak, doru nesneye ait uygun yordam armaya alr tabii bu ilemler srasndan verimlilik der. Eer biz Kedi snfn final yaparsak veya sadece yakalaAv() yordamn finalyaparsak ge balama zelliini kapatm oluruz bylece verimlilik artar. KediKaplan2.java
class Kedi2 {

public final void yakalaAv() { System.out.println("Kedi sinifi Av yakaladi"); } } class Kaplan2 extends Kedi2 { public static void goster(Kedi2 k) { // k.yakalaAv(); // ! dikkat ! } /* iptal edemez public void yakalaAv() { System.out.println("Kaplan sinifi Av yakaladi"); } */ public static void main(String args[] ) { Kedi2 k = new Kedi2() ; Kaplan2 kp = new Kaplan2(); goster(k); goster(kp); } }

KediKaplan2.java rneimizde, yakalaAv() yordamn final yaparak, bu yordamn Kaplan snfnn ierisinde iptal edilmesini engelleriz; yani, ge balama (late binding) zellii kapatm oluruz. Neden Polimorfizm? Neden polimofizm sorusuna yant aramadan nce, polimorfizm zellii olmasayd olaylarn nasl gelieceini nce bir grelim. Nesneye ynelik olmayan programlama dillerini kullanan kiiler iin aadaki rneimiz gayet normal gelebilir. mesaiBasla() yordamnn ierisindeki ifelse ifadelerine dikkat ltfen. IsYeriNon.java
class Calisan { public String pozisyon = "Calisan"; public void calis() { } } class Mudur { public String pozisyon = "Mudur"; public Mudur () { // yaplandrc pozisyon = "Mudur" ; } public void calis() { // iptal etme (override) System.out.println("Mudur Calisiyor"); } } class Programci { public String pozisyon = "Programci"; public Programci() { // yaplandrc pozisyon = "Programci" ; } public void calis() { // iptal etme (override) System.out.println("Programci Calisiyor"); } } class Pazarlamaci { public String pozisyon = "Pazarlamaci"; public Pazarlamaci() { // yapilandirici pozisyon = "Pazarlamaci" ; } public void calis() { // iptal etme (override) System.out.println("Pazarlamaci Calisiyor"); } } public class IsYeriNon { public static void mesaiBasla(Object[] o ) { for ( int i = 0 ; i < o.length ; i++ ) { if ( o[i] instanceof Calisan ) { Calisan c = (Calisan) o[i] ; //aaya evirim

c.calis(); } else if ( o[i] instanceof Mudur ) { Mudur m = (Mudur) o[i] ; //aaya evirim m.calis(); } else if ( o[i] instanceof Programci ) { Programci p = (Programci) o[i] ; //aaya evirim p.calis(); } else if ( o[i] instanceof Pazarlamaci ) { Pazarlamaci paz = (Pazarlamaci) o[i]; //aaya evirim paz.calis(); } //... } } public static void main(String args[]) { Object[] o = new Object[4]; o[0] = new Calisan(); // yukar cevirim (upcasting) o[1] = new Programci(); // yukar cevirim (upcasting) o[2] = new Pazarlamaci(); // yukar cevirim (upcasting) o[3] = new Mudur(); // yukar cevirim (upcasting) mesaiBasla(o); } }

Yukardaki rneimizde nesneye ynelik programlamaya yakmayan davrantr (OOP), mesaiBasla() yordamnn ierisinde yaplmaktadr. Bu yordammzda, dizi ierisindeki elemanlarn teker teker hangi tipte olduklar kontrol edilip, tiplerine gre calis()yordamlar arlmaktadr. Calisan snfndan treteceim her yeni snf iin mesaiBasla() yordamnn ierisinde ayr bir if-else koul ifade yazmak gerekten ok ac verici bir olay olurdu. Polimorfizm bu durumda devreye girerek, bizi bu zahmet veren ilemden kurtarr. ncelikle yukardaki uygulamamzn kts inceleyelim. Programci Calisiyor Pazarlamaci Calisiyor Mudur Calisiyor IsYeriNon.java rneimizi nesneye ynelik programlamaya tekrardan yazlrsa; IsYeri.Java
class Calisan { public String pozisyon="Calisan" ; public void calis() {} } class Mudur extends Calisan { public Mudur () { // yaplandrc pozisyon = "Mudur" ; } public void calis() { // iptal etme (override) System.out.println("Mudur Calisiyor"); } } class Programci extends Calisan { public Programci() { // yaplandrc pozisyon = "Programci" ; } public void calis() { // iptal etme (override) System.out.println("Programci Calisiyor"); } } class Pazarlamaci extends Calisan { public Pazarlamaci() { // yaplandrc pozisyon = "Pazarlamaci" ; } public void calis() { // iptal etme (override) System.out.println("Pazarlamaci Calisiyor"); } } public class IsYeri { public static void mesaiBasla(Calisan[] c ) { for (int i = 0 ; i < c.length ; i++) { c[i].calis(); // !Dikkat! } } public static void main(String args[]) { Calisan[] c = new Calisan[4]; c[0] = new Calisan(); // yukar cevirim gerekmiyor c[1] = new Programci(); // yukar cevirim (upcasting) c[2] = new Pazarlamaci(); // yukar cevirim (upcasting) c[3] = new Mudur(); // yukar cevirim (upcasting) mesaiBasla(c); }

Grld zere mesaiBasla() yordam artk tek satr, bunu polimorfizm ve tabii ki ge balamaya borluyuz. Bu sayede artk Calisansnfndan istediim kadar yeni snf tretebilirim, yani geniletme olayn rahatlkla yapabilirim hem de mevcut yapy bozmadan. Uygulamann ktsnda aadaki gibidir. Programci Calisiyor Pazarlamaci Calisiyor Mudur Calisiyor Bu uygulamadaki snflara ait UML diyagram aadaki gibidir.

Kullanlan snf yaps Geniletilebilirlik (Extensibility) Polimorfizm sayesinde geniletebilirlik olay ok basite indirgenmi bulunmaktadr. Geniletebilirlik, mevcut hiyerariyi kaltm yolu ile geniletmedir. imdi IsYeri.java rneimizi biraz daha geniletelim; Yeni uygulamamzn adn BuyukIsYeri.java yapalm, bu uygulamamz iin, snflara ait UML diyagram aadaki gibidir;

Yukardaki UML diyagramnda grld zere mevcut hiyerariyi genilettik ve toplam 4 adet yeni snf sistemimize eklendik (GenelMudur, AnalizProgramci, SistemProgramci, Sekreter). Yukardaki UML emas Java uygulamasna evrilirse: BuyukIsyeri.java
class Calisan { public String pozisyon ; public void calis() {} } class Mudur extends Calisan { public Mudur () { // yaplandrc pozisyon = "Mudur" ; } public void calis() { // iptal etme (override) System.out.println("Mudur Calisiyor"); } } class GenelMudur extends Mudur { public GenelMudur () { // yaplandrc pozisyon = "GenelMudur" ; } public void calis() { // iptal etme (override) System.out.println("GenelMudur Calisiyor"); } public void toplantiYonet() { System.out.println("GenelMudur toplanti yonetiyor"); } } class Programci extends Calisan { public Programci() { // yaplandrc pozisyon = "Programci" ; } public void calis() { // iptal etme (override) System.out.println("Programci Calisiyor"); } } class AnalizProgramci extends Programci { public AnalizProgramci() { // yaplandrc pozisyon = "AnalizProgramci" ;

} public void analizYap() { System.out.println("Analiz Yapiliyor"); } } class SistemProgramci extends Programci { public SistemProgramci() { // yaplandrc pozisyon = "SistemProgramci" ; } public void sistemIncele() { System.out.println("Sistem Inceleniyor"); } } class Pazarlamaci extends Calisan { public Pazarlamaci() { // yaplandrc pozisyon = "Pazarlamaci" ; } public void calis() { // iptal etme (override) System.out.println("Pazarlamaci Calisiyor"); } } class Sekreter extends Calisan { public Sekreter() { // yaplandrc pozisyon = "Sekreter" ; } public void calis() { // iptal etme (override) System.out.println("Sekreter Calisiyor"); } } public class BuyukIsYeri { public static void mesaiBasla(Calisan[] c ) { for (int i = 0 ; i < c.length ; i++) { c[i].calis(); // ! Dikkat ! } } public static void main(String args[]) { Calisan[] c = new Calisan[7]; c[0]=new Calisan(); //yukar cevirim gerekmiyor c[1]=new Programci(); //yukar cevirim (upcasting) c[2]=new Pazarlamaci(); // yukar cevirim (upcasting) c[3]=new Mudur(); // yukar cevirim (upcasting) c[4]=new GenelMudur(); // yukar cevirim (upcasting) c[5]=new AnalizProgramci(); // yukar cevirim (upcasting) c[6]=new SistemProgramci(); // yukar cevirim (upcasting) mesaiBasla(c); } }

Yukardaki rnekte dikkat edilirse mesaiBasla() yordam hala tek satr. Uygulamann kts aadaki gibidir; Programci Pazarlamaci Mudur GenelMudur Programci Programci Calisiyor Calisiyor Calisiyor Calisiyor Calisiyor Calisiyor

Burada yaplan i, Calisan snfndan yeni snflar tretmektir, bu yeni tretilmi snflarn (GenelMudur, AnalizProgramci, SistemProgramci, Sekreter) calis() yordamlarn armak iin ekstra bir yk stlenilmedi (mesaiBaslat() yordamnn ierisine dikkat edersek ). Polimorfizm ve tabii ki ge balama sayesinde bu iler otomatik olarak gereklemektedir. Soyut Snflar ve Yordamlar (Abstract Classes and Methods) Soyut kavramn anlatmadan nce, IsYeri.java ve BuyukIsyeri.java rneklerini inceleyelim. Bu uygulamalarn ierisinde hi bir i yapmayan ve sanki bouna oraya yerletirilmi hissi veren bir snf gze arpar; evet bu Calisan snfdr. Calisan snfn daha yakndan baklrsa;
class Calisan { public String pozisyon = "Calisan"; public void calis() {} }

Yukarda grld zere Calisan snf hi bir i yapmamaktadr. Akllara yle bir soru daha gelebilir "Madem ki Calisan snf hi bir i yapmyor,

ne diye onu oraya yazdk"; cevap: birletirici bir rol oynad iin, Calisan snfn oraya yazdk diyebilirim. Olaylar biraz daha detaylandralm. Soyut snflar, u ana kadar bildiimiz snflardan farkldrlar. Soyut (abstract) snflarmz direk new() ile oluturamayz. Soyut snflarn var olmasndaki en byk sebeplerden biri birletirici bir rol oynamalardr. Soyut bir snftan tretilmi alt snflara ait nesneler, ok rahat bir ekilde yine bu soyut snf tipindeki referanslara balanabilirler (yukar evirim). Bylece polimorfizm ve ge balamann kullanlmas mmkn olur. Bir snfn soyut olmas iin, bu snfn ierisinde en az bir adet soyut yordamnn bulunmas gerekir. Soyut yordamlarn gvdesi bulunmaz; yani, ii bo hibir i yapmayan yordam grnmndedirler. Soyut bir snfdan tretilmi alt snflar, bu soyut snfn ierisindeki soyut yordamlar kesin olarak iptal etmeleri (override) gerekmektedir. Eer tretilmi snflar, soyut olan ana snflarna ait bu soyut yordamlar iptal etmezlerse, derleme annda (compile-time) hata ile karlalr.
abstract void calis() ; // gvdesi olmayan soyut yordam

Soyut snflarn ierisinde soyut yordamlar olaca gibi, gvdeleri olan, yani i yapan yordamlarda bulunabilir. Buraya kadar anlattklarmz bir uygulama zerinde pekitirelim; AbIsyeri.java
abstract class Calisan { public String pozisyon="Calisan" ; public abstract void calis() ;// soyut yordam public void zamIste() { // soyut olmayan yordam System.out.println("Calisan zamIste"); } } class Mudur extends Calisan { public Mudur () { // yaplandrc pozisyon = "Mudur" ; } public void calis() { // iptal etme (override) System.out.println("Mudur Calisiyor"); } } class Programci extends Calisan { public Programci() { // yaplandrc pozisyon = "Programci" ; } public void calis() { // iptal etme (override) System.out.println("Programci Calisiyor"); } public void zamIste() { // iptal etme (override) System.out.println("Programci Zam Istiyor"); } } class Pazarlamaci extends Calisan { public Pazarlamaci() { // yaplandrc pozisyon = "Pazarlamaci" ; } public void calis() { // iptal etme (override) System.out.println("Pazarlamaci Calisiyor"); } } public class AbIsYeri { public static void mesaiBasla(Calisan[] c ) { for (int i = 0 ; i < c.length ; i++) { c[i].calis(); // !Dikkat! } } public static void main(String args[]) { Calisan[] c = new Calisan[3]; // c[0] = new Calisan(); // soyut snflar new ile direk oluturulamazlar c[0] = new Programci(); // yukar cevirim (upcasting) c[1] = new Pazarlamaci();// yukar cevirim (upcasting) c[2] = new Mudur(); // yukari cevirim (upcasting) mesaiBasla(c); } }

Yukardaki rneimizi incelersek, soyut (abstract) olan Calisan snfnn 2 adet yordam olduu grrz. Bu iki yordamdan bir tanesi olan soyut (abstract) calis() yordamdr. Calisan snfndan treyen snflar tarafndan bu yordam kesin kes iptal edilmek (override) zorundadr. Batan aklarsak, eer bir snfn ierisinde soyut (abstract) bir yordam varsa o zaman bu snf da soyut (abstract) olmak zorundadr. Fakat soyut olan snflarn ierisinde normal yordamlarda bulunabilir ayn zamIste() yordamnn Calisan snfnn ierisinde bulunduu gibi.

Calisan snfndan treyen dier snflar incelenirse, bu snflarn hepsinin, calis() yordamn iptal ettikleri (override) grlr ama ayn zamanda zamIste() yordam sadece Programci snfnn ierisinde iptal edilmitir (override). Eer ana snfn ierisindeki bir yordamn tremi snflar ierisinde iptal edilmeleri (override) ansa braklmak istenmiyorsa; o zaman bu yordamn soyut olarak tanmlanmas gerekir. Dikkat edilmesi gereken bir baka nokta, soyut snflarn direk olarak new() ile oluturulamyor olmasdr. Soyut snf demek birletirici rol oynayan snf demektir. AbIsYeri.java uygulamasndaki snflara ait UML diyagram aadaki gibidir;

AbIsYeri.java uygulamasnda kullanlan snflar UML diyagramndan daha net bir biimde grmekteyiz ki tremi snflar, ana snfa ait calis() yordamn iptal etmek (override) zorunda braklmlardr. Fakat zamIste() yordam ise sadece Calisan snfndan tremi olan Programci snf ierisinde iptal edilmitir (override). Niye Soyut Snf ve Yordamlara htiya Duyarz? rnein hem cep telefonunun ekranna hem de monitrn ekranna izgi izdirmek istiyoruz fakat cep telefonu ekrannn zellikleri ile monitr ekrannn zelliklerinin birbirinden tamamen farkl olmas, karmzda byk bir problemdir. Bu iki ekrana izgi izdirmek iin deiik snflara ihtiya duyulaca kesindir. Peki nasl bir yazlm tasarm yaplmaldr. CizimProgrami.java
abstract class Cizim { // soyut yordam public abstract void noktaCiz(int x , int y) ; // soyut olmayan yordam public void cizgiCiz(int x1 , int y1 , int x2 , int y2) { // noktaCiz(x,y); // yordamn kullanarak ekrana cizgi ciz } } class CepTelefonuCizim extends Cizim { // iptal ediyor (override) public void noktaCiz(int x, int y) { // cep telefonu ekrani icin nokta ciz..... } } class MonitorCizim extends Cizim { // iptal ediyor (override) public void noktaCiz(int x, int y) { // Monitor ekrani icin nokta ciz..... } } public class CizimProgrami { public void baslat(int x1 , int y1 , int x2 , int y2) { // cep telefonunun ekranina cizgi cizmek icin Cizim c1 = new CepTelefonuCizim(); c1.cizgiCiz(x1 , y1 , x2 , y2); // Monitor ekranina cizgi cizmek icin Cizim c2 = new MonitorCizim(); c2.cizgiCiz(x1 , y1 , x2 , y2 ); } }

Cizim snfmzn ierisinde bulunan cizgiCiz() yordam soyut (abstract) deildir fakat noktaCiz() yordam soyuttur, neden? Sebebi,cizgiCiz() yordamnn ekranlara izgi izmek iin noktaCiz() yordamna ihtiya duymasndan kaynaklanr. cizgiCiz() yordamnn ihtiya duyduu tek ey, ekran zerinde tek bir noktann nasl izileceini bilmektir, bu bilgiler cizgiCiz() yordamna verildii srece sorun yaanmayacaktr. Ekrana tek bir noktann nasl izileceini, Cizim snfndan tremi alt snflar tarafndan verilmektedir. Cizim snfndan tremi snflara dikkat edilirse (CepTelefonuCizim ve MonitorCizim), bu snflarn ierisinde, ana snfa ait olannoktaCiz() yordamnn iptal edilmi (override) olduunu grrz. Bunun sebebi her bir ekrana (Monitrn ve Cep telefonu ekran) ait nokta iziminin farkl olmasndan kaynaklanr. Yukardaki uygulamamza ait snflar iin UML diyagram aadaki gibidir.

CizimProgrami.java uygulamasnda kullanlan snflar Yukardaki rneimizden kartlacak olan ana fikir yledir; eer bir ilem deiik verilere ihtiya duyup ayn ii yapyorsa, bu ilem soyut (abstract) snfn ierisinde tanmlanmaldr. Yaplandrclar erisindeki lgin Durumlar Yaplandrclar ierisinde ne gibi ilgin durumlar olabilir ki diyebilirsiniz? Biraz sonra gstereceimiz rnek ierisinde polimorfizm ve ge balamann devreye girmesiyle olaylar biraz karacaktr. ncelikle yaplandrclarn ne ie yaradklarn bir tekrar edelim. Bir nesne kullanma gemeden nce baz ilemler yapmas gerekebilir, rnein global olan alanlarna ilk deerlerinin verilmesi gerekebilir veya JDBC (Daha sonraki yazlarmzda deinmeye alacaz) balants ile veritaban balanp baz ilemleri yerine getirmesi gerekebilir, rnekleri oaltmak mmkndr... Tm bu ilemlerin yaplmas iin gereken yer yaplandrclardr. Buraya kadar sorun yoksa rneimizi incelemeye balayabiliriz. Spor.java
abstract class Sporcu { public abstract void calis(); public Sporcu() { // yaplandrc yordam System.out.println("calis() cagrilmadan nce"); calis(); // ! Dikkat ! System.out.println("calis() cagrildiktan sonra"); } } class Futbolcu extends Sporcu { int antraman_sayisi = 4 ; public void calis() { System.out.println("Futbolcu calis() " + antreman_sayisi ); } public Futbolcu() { // yaplandrc yordam System.out.println("Futbolcu yapilandirici" ); calis(); } } public class Spor { public static void main( String args[] ) { Futbolcu f = new Futbolcu(); // Sporcu s = new Sporcu(); // ! Hata soyut snf ! } }

Soyut snflara ait yaplandrclar olabilir. Bir nceki yazmzda da inceledii zere, snflara ait nesneleri olutururken iin ierisinde bir de kaltm (inheritance) zellii girdiinde olaylarn nasl deitii incelemitik. Bir snfa ait nesne oluturulacaksa, nce bu snfn ana snf var m diye kontrol edilir; yani, bu snf tretilmi bir snf m kontrol yaplr. Eer bu snfn tretildii ana bir snf var ise nce bu ana snfa ait nesne oluturulur daha sonra sra treyen snfmza ait nesnenin oluturulmasna gelir. Yukardaki rneimizde kaltm kavram kullanlmtr. Ana

snf Sporcu snfdr, bu snftan tretilmi olan ise Futbolcu snfdr. Futbolcu bir Sporcudur. Biz Futbolcu snfna ait bir nesne oluturmak istersek, bu olayn daha ncesinde Sporcu snfna ait bir nesnesinin oluacan aktr. Bu rneimizdeki akl kartrc nokta, soyut bir snfa ait yaplandrc ierisinden soyut bir yordamn arlyor olmasdr. Sporcusnfnn yaplandrcsna dikkat ederseniz, bu yaplandrc ierisinden soyut bir yordam olan calis() yordam arlmtr. calis() yordam hangi amala soyut yaplm olabilir? Bu yordamn soyut yaplmasndaki tek ama, alt snflarn bu yordam iptal etmelerini kesinletirmekolabilir. Bu rneimizdeki yanl, soyut bir snfa ait yaplandrcnn ierisinden soyut bir yordamn arlmasdr. Peki byle bir yanl yapldnda nasl sonular oluur? Uygulamamzn kts aadaki gibidir. calis() Futbolcu calis() calis() Futbolcu Futbolcu calis() cagrilmadan nce 0 --> dikkat cagrildiktan sonra yapilandirici 4

Uygulama ktsndaki 2. satr ok ilgintir. Oluan olaylar adm adm aklarsak; Futbolcu snfna ait bir nesne oluturulmak istendi ama Futbolcu snf Sporcu snfndan tretildii iin, ilk nce Sporcu snfna ait yaplandrc carlacaktr. Sporcu snfna ait yaplandrcnn ierisinde soyut olan calis() yordam arld. Soyut olan calis() yordam Futbolcu snfnn ierisinde iptal edildii (override) iin, Futbolcu snfna ait olan calis() yordam arlacaktr fakat temel (primitive) int tipinde olan antreman_sayisialanna henz ilk deeri atanmadndan, Java tarafndan varsaylan deer (default value) olan 0 says verilmitir. Buradaki ilgin olan nokta Futbolcu snfnn ierisindeki calis() yordam, Futbolcu snfna ait yaplandrcdan bile nce arlm olmasdr (-ki bu istenmeyen bir durumdur). Ana snf olan Sporcu snfna ait yaplandrcnn almas sona erdikten sonra tremi snf olan Futbolcu nesnesine ait global alan olanantreman_sayisi alannn ilk deeri verilmitir. En son olarak Futbolcu snfna ait yaplandrc ierisindeki kodlar altrlarak ilem sona erer. Kaltm ve Yukar evirim (Upcasting) Yukar evirim (upcasting) her zaman gvenlidir, sonuta daha zellikli bir tipten daha genel bir tipe doru evirim gereklemitir. rnein elimizde iki tip televizyon bulunsun, biri Xmodel televizyon dieri Xmodelden tretilmi ve daha yeni zelliklere sahip olan Ymodel televizyon. Bu ilikiyi UML diyagramnda gsterirsek.

Televizyon.java Kaltm ve Yukar evirim UML diyagram Java uygulamasna dntrrse;


class Xmodel { public void sesAc() { System.out.println("X model televizyon sesAc()"); } public void sesKapa() {

System.out.println("X model televizyon sesKapa()"); } public void kanalDegistir() { System.out.println("X model televizyon kanalDegistir()"); } } class Ymodel extends Xmodel { public void sesAc() { // iptal etme (override) System.out.println("Y model televizyon sesAc()"); } public void sesKapa() { // iptal etme (override) System.out.println("Y model televizyon sesKapa()"); } public void kanalDegistir() { // iptal etme (override) System.out.println("Y model televizyon kanalDegistir() "); } public void teleText() { System.out.println("Y model televizyon teleText()"); } } public class Televizyon { public static void main(String args[]) { // yukar cevirim ( upcasting ) Xmodel x_model_kumanda = new Ymodel(); x_model_kumanda.sesAc(); x_model_kumanda.sesKapa(); x_model_kumanda.kanalDegistir(); //!! hata !!, bu kumandann byle bir dmesi yok :) // x_model_kumanda.teleText() ; } }

Yukar evirim (upcasting) olaynda iki taraf vardr, bir tanesi heap alannda nesnenin kendisi dier tarafta yn (stack) alannda bulunan referans. Olaylara televizyon ve kumanda boyutunda bakarsak iin srr zlmeye balar. Elimizde Xmodel televizyon kumandas olduunu dnn ama kumanda Ymodel bir televizyonu gsterirsin (gsterebilir nk arada kaltm ilikisi vardr (Ymodel televizyon bir Xmodeltelevizyondur), o zaman karmzda duran Ymodel televizyonun teleText() zellii olmasna ramen bunu kullanamayz nk Xmodel bir televizyon kumandas, Xmodel televizyon iin tasarlandndan, bu kumandann zerinde teleText() dmesi olmayacaktr. Anlattklar ekil zerinde gsterilirse:

Televizyon.java Kaltm ve Yukar evirim Aaya evirim (Downcasting) Aaya evirim (downcasting), yukar evirim (upcasting) ileminin tam tersidir. Aaya evirim (downcasting), daha genel bir tipten, daha zellikli bir tipe doru gei demektir ve tehlikelidir. Tehlikelidir nk evrilmeye allan daha zellikli tipe doru evirim esnasnda sorun kma riski yksektir. Java programlama dilinde aaya evirim (downcasting) yaparken, hangi tipe doru evirim yaplaca ak olarak belirtmelidir. Fakat yukar evirim (upcasting) ileminde byle bir belirte koyma zorunluluu yoktur nk oradaki olay daha zellikli bir tipten daha genel bir tipe doru evirimdir; yani, gvenlidir. Anlattklar rnek zerinde gsterirsek: Televizyon2.java
class Xmodel { public void sesAc() { System.out.println("X model televizyon sesAc()"); } public void sesKapa() { System.out.println("X model televizyon sesKapa()"); } public void kanalDegistir() { System.out.println("X model televizyon kanalDegistir()"); } }

class Ymodel extends Xmodel { public void sesAc() { // iptal etme (override) System.out.println("Y model televizyon sesAc()"); } public void sesKapa() { // iptal etme (override) System.out.println("Y model televizyon sesKapa()"); } public void kanalDegistir() { // iptal etme (override) System.out.println("Y model televizyon kanalDegistir() "); } public void teleText() { System.out.println("Y model televizyon teleText()"); } } public class Televizyon2 { public static void main(String args[]) { Object[] ob = new Object[2] ; ob[0] = new Xmodel() ; // yukari cevirim (upcasting) ob[1] = new Ymodel() ; // yukari cevirim (upcasting) for (int i = 0 ; i < ob.length ; i++) { // asagiya cevirim (Downcasting) Xmodel x_model_kumanda = (Xmodel) ob[i] ; x_model_kumanda.sesAc(); x_model_kumanda.sesKapa(); x_model_kumanda.kanalDegistir(); // x_model_kumanda.teleText(); // bu kumanda da byle bir dme yok System.out.println("----------------------------------"); } } }

Yukardaki uygulamann kts aadaki gibidir; X model televizyon sesAc() X model televizyon sesKapa() X model televizyon kanalDegistir() ----------------------------------------------Y model televizyon sesAc() Y model televizyon sesKapa() Y model televizyon kanalDegistir() ----------------------------------------------Bu rneimizde, Xmodel ve Ymodel nesnelerimiz, Object snf tipindeki dizinin ierisine atlmaktadr. Her snf, Object snfndan tretildii gre, Object snf tipindeki bir dizisinin ierisine Xmodel ve Ymodel nesnelerini rahatlkla atabiliriz buradaki olay yukar doru evirimdir (upcasting). Artk elimizde Object snf tipinde bir dizisi var. Bunun ierisindeki elemanlar tekrardan eski hallerine sokmak iin aaya doru evirim (downcasting) zelliini kullanmak gereklidir. Daha nceden de ifade edildii gibi aaya doru evirim (downcasting) yaplacaksa, bunun hangi tipe olaca ak olarak belirtilmelidir. for ifadesinin ierisine dikkat edilirse, Object tipindeki dizisinin ierisindeki elemanlar Xmodel nesnesine dntrmek iin aadaki ifade kullanlmtr.
// asagiya dogru cevirim (Downcasting) Xmodel x_model_kumanda = (Xmodel) ob[i] ;

Yukardaki ifade sayesinde Object snf tipinde olan dizimizin ierisindeki elemanlar, Xmodel nesnesine evirmi bulunmaktayz. Aslnda bu rneimizde zarardayz, niye derseniz hemen aklayalm. Sonuta bizim iki adet hem Xmodel hem de Ymodel nesnelerimiz vard. Biz bunlar Object snf tipine evirerek yani yukar evirim yaparak Object snf tipindeki dizisinin ierisine yerletirdik, buraya kadar sorun yok. Fakat Object dizisinin ierisinden elemanlarmz ekerken, bu elemanlarmzn hepsini Xmodel nesnesine evirdik yani aaya evirim yapm olduk. Biz byle yapnca Ymodel nesnemiz yok olmu gibi oldu. Yukar doru evirim (upcasting) yaparken, asl nesnelerimiz deerlerinden birey kaybetmezler. rnein bu uygulamamzda bir Objectsnf tipindeki dizimizin ierisine Xmodel ve Ymodel nesnelerini atabildik (bunun sebebinin kaltmdr). Xmodel ve Ymodel nesnelerini,Object nesnelerine evirerek, bu nesnelerimizin asl tiplerini deitirmeyiz, sadece Object dizisinin ierisine atma izni elde ederiz; yani,Object snf tipindeki dizimizin ierisindeki nesnelerimizin orijinal halleri hala Xmodel ve Ymodel tipindedir. Java alma annda (run-time) nesnelerin tiplerini kontrol eder.Eer bu ilemlerde bir uyumsuzluk varsa bunu hemen kullancya ClassCastException istisnas frlatarak bildirir. Nesne tiplerinin alma anndan (run-time) tanmlanmas (RTTI : Run Time Type Identification), kodu yazan kii asndan byk faydalar ierir. Bu aklamalardan yola klarak, yukardaki uygulama deitirilirse. Televizyon3.java
class Xmodel { public void sesAc() { System.out.println("X model televizyon sesAc()");

} public void sesKapa() { System.out.println("X model televizyon sesKapa()"); } public void kanalDegistir() { System.out.println("X model televizyon kanalDegistir()"); } } class Ymodel extends Xmodel { public void sesAc() { // iptal ediyor (override) System.out.println("Y model televizyon sesAc()"); } public void sesKapa() { // iptal ediyor (override) System.out.println("Y model televizyon sesKapa()"); } public void kanalDegistir() { // iptal ediyor (override) System.out.println("Y model televizyon kanalDegistir() "); } public void teleText() { System.out.println("Y model televizyon teleText()"); } } public class Televizyon3 { public static void main(String args[]) { Object[] ob = new Object[2] ; ob[0] = new Xmodel() ; ob[1] = new Ymodel() ; for (int i = 0 ; i < ob.length ; i++) { Object o = ob[i] ; if (o instanceof Ymodel) { // RTTI Ymodel y_model_kumanda = (Ymodel) o ; //artk gvende y_model_kumanda.sesAc(); y_model_kumanda.sesKapa(); y_model_kumanda.kanalDegistir(); y_model_kumanda.teleText() ; } else if (o instanceof Xmodel) { // RTTI Xmodel x_model_kumanda = (Xmodel) o; // artik guvenli x_model_kumanda.sesAc(); x_model_kumanda.sesKapa(); x_model_kumanda.kanalDegistir(); } } } }

Object snf tipindeki dizi ierisinde bulunan elemanlarn hepsinin Object snf tipinde olma zorunluluu olduunu biliyoruz. Xmodel veYmodel televizyonlar yukar doru evirim zellii sayesinde Object snf tipine evirerek, Object snf tipindeki dizi ierisine atabildik. Peki Xmodel ve Ymodel nesnelerimizin zelliklerini sonsuza kadar geri alamayacak myz? Geri almann yolu aaya evirimdir (downcasting). Aaya evirimin (downcasting) tehlikeli olduunu biliyoruz. Eer yanl bir tipe doru evirim yaparsak, alma annda Java tarafndanClassCastException istisnas ile durduruluruz. alma annda (run-time) yanl bir tipe evirimden korkuyorsak instanceof anahtarkelimesini kulanmamz gerekir. Yukardaki rneimizde (Televizyon3.java) instanceof anahtar kelimesi sayesinde alma annda, Objectsnf tipindeki dizi ierisindeki elemanlarn asl tiplerini kontrol ederek aaya doru evirim yapma imkanna sahip oluruz. Bylece hata oluma riskini minimuma indirgeriz. Uygulamamzn kts aadaki gibidir; X model televizyon sesAc() X model televizyon sesKapa() X model televizyon kanalDegistir() Y model televizyon sesAc() Y model televizyon sesKapa() Y model televizyon kanalDegistir() Y model televizyon teleText()

You might also like