Previous
Next

JAVA - Polymorphism(Çok biçimlilik) nedir?

by Cem Kefeli 16. Eylül 2009 04:28

JavaÇok biçimlilik(Polymorphism), kalıtım(Inheritance) ile iç içe geçmiş ilk bakışta karışık gibi görünen, hatta ne gerek var bunlara dedirten, bir yapıya sahiptir. Fakat işin içerisine girdikten sonra ne gibi kolaylıklar ve güzellikler sağladığını görünce dil tasarımcılarına hakkını teslim etmek kaçınılmaz oluyor. En genel anlamda, oluşturduğumuz nesnelerin gerektiğinde kılıktan kılığa girip başka bir nesneymiş gibi davranabilmesine polimorfizm diyebiliriz. Peki ne demek şimdi bu cümle?

Olaya ilk önce nesne kalıtımından kısaca söz ederek başlamak istiyorum. OOP(Object Oriented Programming) diyorsak nesnelerden bahsediyoruz demektir bu. Herşey nesne olarak düşünülebilir. Nesneler ise birbirlerinden türeyebilmektedir. Örneğin bir ana sınıf düşünün aklınızda, bir de bu ana sınıfın yavrucuklarını düşünün. Yavrucukları diyorum ama, bunu yavru sınıflar daha küçüktür, daha az öğe içerir gibi düşünmeyin sakın. Tam tersine bu yavrucuklar daha gelişkin olabilirler. Annelerinin tüm özelliklerine sahip olurlar da, hatta bir de annelerinden farklı başka özellikler de içerebilirler. Bu yavrucukların da yavrucukları olabilir. Bu böyle devam eder gider...

Polymorphism UMLSağ tarftaki UML diagramında bir kalıtım yapısı bulunmakta. KISI ana sınıfından PERSONEL isimli yeni bir sınıf ve PERSONEL sınıfındanda da MUHENDIS ve TEKNISYEN olmak üzere iki farklı sınıf türetilmiştir. MUHENDIS ve TEKNISYEN bir PERSONEL'dir. PERSONEL ise bir KISI'dir türünde ifadelerin kurulabildiği her yerde kalıtımdan söz etmek mümkündür. Böylece bu nesnelerin arasında artık kalıtımı ilişkisi kurulmuş olur. PERSONEL sınıfı KISI sınıfında yer alan BenKimim isimli fonksiyonu override etmiş yani geçersiz kılmıştır. Bu fonksiyon için kendisi bir içerik oluşturmuştur. Aynı şekilde MUHENDIS ve TEKNISYEN sınıfları da kendi içeriklerini BenKimim fonksiyonu içerisine yerleştirmiştir. Sınıfların tanımlamalarını da aşağıda vermekteyim.

Main.java  |  Netbeans Projesini indir Polymorphism1.rar (14,80 kb)  |  Gizle  |  Göster
package polymorphism1;
 												
 /**
 *
 * @author Cem KEFELİ
 * http://www.cemkefeli.com
 */
public class Main
{
	static public class KISI
	{
		public void BenKimim()
		{
			System.out.println("Ben herhangi bir kisiyim.");
		}
	}
	static public class PERSONEL extends KISI
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir personelim.");
		}
	}
	static public class MUHENDIS  extends PERSONEL
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir mühendisim.");
		}
	}
	static public class TEKNISYEN  extends PERSONEL
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir teknisyenim.");
		}
	}
	static public void KimimOnuYaz(KISI Birisi)
	{
		Birisi.BenKimim();
	}
	public static void main(String[] args) 
	{
		KISI Insan1=new KISI();
		PERSONEL Insan2=new PERSONEL();
		MUHENDIS Insan3=new MUHENDIS();
		TEKNISYEN Insan4=new TEKNISYEN();
		KimimOnuYaz(Insan1);
		KimimOnuYaz(Insan2);
		KimimOnuYaz(Insan3);
		KimimOnuYaz(Insan4);
	}
}	
Program Çıktısı

Polymorphism örnek 1Kodu incelediğimizde görürüz ki olanlar aslında polimorfizmin ta kendisidir. Şöyle ki; KimimOnuYaz fonksiyonu parametre olarak yalnızca KISI sınıfı türünde değişkenleri kabul etmektedir. Fakat biz bu fonksiyon içerisine her dört sınıfın örneklerini de(KISI, PERSONEL, MUHENDIS, TEKNISYEN) gönderebildik ve herhangi bir hata ile de karşılaşmadık. Herhangi bir hata ile karşılaşmadığımız gibi üstüne üstlük çok güzel bir durum ile de karşılaştık. Peki bu iş nasıl oldu? Şimdi bu güzel durumu incelemeye çalışacağız.
Main fonksiyonu içerisinde dört sınıfa ait nesne örneklerimizi oluşturduk. sonrasında ilk önce KISI türünden Insan1 referansını KimimOnuYaz isimli fonksiyona gönderdik. Burada bir tuhaflık yok, çünkü KimimOnuYaz fonksiyonu zaten giriş parametresi olarak KISI nesnesini seviyor. Dolayısı ile KimimOnuYaz içerisindeki Birisi nesne örneğinin BenKimim fonksiyonu çağırılmış oldu. Birisi referansının türü KISI olduğu için KISI sınıfının BenKimim fonksiyonu çağırıldı. İkinci olarak ise Insan2 referansı KimimOnuYaz fonksiyonu tarafından giriş olarak alındı. İşte burada dikkat etmemiz gereken önemli bir nokta var. KimimOnuYaz fonksiyonu yalnızca KISI sınıfına ait nesne örneklerini kabul ettiği için tam bu satırda bir tür dönüşümü işlemi yapıldı. Bu işleme UpCasting adı verilmektedir. Yani tam olarak şu oldu aslında, KimimOnuYaz fonksiyonu içerisindeki KISI türünden Birisi nesnesi birçok kılığa birden bürünüverdi bir anda. Yeri geldi KISI nesne türünden bir nesne örneği oldu, yeri geldi TEKNİSYEN nesne türünden bir nesne örneği oluverdi bir anda. Birisi ismindeki nesne örneği kendi sınıfı olan KISI ve KISI sınıfından türeyen diğer nesne örneklerine bağlanabildi. Sonuç olarak ise Birisi referansının nesne türü ne ise o nesneye ait BenKimim fonksiyonu çağırıldı. İşte size Polimorfizm!!!   

Bu kod satırlarının arkasında saklı olan bir diğer kavram ise Geç Bağlama(Late Binding)'dır. Geç bağlamayı temel olarak bir nesne örneğinin hangi nesneye bağlandığı ve hangi nesneye ait olduğunun çalışma zamanında(Run Time) belli olması olarak tanımlayabilirim. Eğer siz bir nesne örneği oluşturur ve bu referansın herhangi bir öğesine ulaşmak isterseniz bu derleme zamanında(Compile Time) ortaya çıkan bir durumdur. Yani referansa ve bu referansın bağlandığı nesneye ait herşey gayet açıktır. Fakar yukarıdaki örneğimizdeki gibi bir yöntem uygulayacak olursanız bu sefer referans nesnenin bağlandığı nesne belirli değildir ve run time sırasında belli olmaktadır. Tıpkı Birisi referansının yeri geldiğinde KISI sınıfına bağlanması yeri geldiğinde ise PERSONEL sınıfına bağlanması gibi.

Peki bu örnek ile çok biçimliliği kanıtladık ama bu çok biçimlilik ne işe yarar ki? Nerelerde ihtiyaç duyacağız ki biz böyle bir şeye? Doğal olarak kullanım alanı olmayan bir şeyin gerekliliği de tartışılır. Yukarıdaki örnek aslında gözümüze çok hoş göründüğü için sanki olağan birşeymiş gibi karşılıyor olabilirsiniz. Zaten yukarıdaki programcıktaki gibi bir işi yaptırabilmek için böyle bir kod yazmak gerekirdi diyebilirsiniz ama hiç de öyle değil. Eğer çok biçimlilik bizim hizmetimize sunulmamış olsaydı aşağıdaki gibi kalabalık ve hiç de hoş görünmeyen son derede adaptif olmayan bir yönteme baş vurmak zorunda kalacaktık. Bu internette yaptığım aramalarda çok sıklıkla karşıma çıkan ve olayı çok güzel özetleyen bir örnek olacak.

Main.java  |  Netbeans Projesini indir Polymorphism2.rar (16,00 kb)  |  Gizle  |  Göster
package polymorphism2;
 
 /**
 *
 * @author Cem KEFELİ
 * http://www.cemkefeli.com
 */
public class Main
{
	static public class KISI
	{
		public void BenKimim()
		{
			System.out.println("Ben herhangi bir kisiyim.");
		}
	}
	static public class PERSONEL extends KISI
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir personelim.");
		}
	}
	static public class MUHENDIS  extends PERSONEL
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir mühendisim.");
		}
	}
	static public class TEKNISYEN  extends PERSONEL
	{
		@Override
		public void BenKimim()
		{
			System.out.println("Ben bir teknisyenim.");
		}
	}
	static public void KimimOnuYaz(KISI Birisi)
	{
		//Birisi.BenKimim();
		if(Birisi instanceof KISI)
		{
			KISI Obje=(KISI)Birisi;
			Obje.BenKimim();
		}
		else if(Birisi instanceof PERSONEL)
		{
			PERSONEL Obje=(PERSONEL)Birisi;
			Obje.BenKimim();
		}
		else if(Birisi instanceof MUHENDIS)
		{
			MUHENDIS Obje=(MUHENDIS)Birisi;
			Obje.BenKimim();
		}
		else if(Birisi instanceof TEKNISYEN)
		{
			TEKNISYEN Obje=(TEKNISYEN)Birisi;
			Obje.BenKimim();
		}
	}
	public static void main(String[] args)
	{
		KISI Insan1=new KISI();
		PERSONEL Insan2=new PERSONEL();
		MUHENDIS Insan3=new MUHENDIS();
		TEKNISYEN Insan4=new TEKNISYEN();
		KimimOnuYaz(Insan1);
		KimimOnuYaz(Insan2);
		KimimOnuYaz(Insan3);
		KimimOnuYaz(Insan4);
	}
}
Program Çıktısı

Polymorphism örnek 2Aslında bu örneği gördükten sonra olayı anlamış olmalısınız. Az önce tek bir satırlık kod ile kolay ve çok güzel bir şekilde hallettiğimiz işimizi artık satırlarca kod yazarak ancak görebiliyoruz. Evet iki programcık da aynı işi yapıyor ve hiç bir farkları yok birbirlerinden. Aslında program çıktısı olrak değil de performans olarak ufak bir farkları var, Bu konuya yazının sonuna doğru geleceğim. İkinci yöntemin çok da hoş olmadığı açık. KimimOnuYaz fonksiyonuna yine temel sınıf ve bu sınıftan türeyen nesne örneklerini gönderiyoruz fakat çok biçimliliği uygulayamadığımız için gelen nesne örneklerinin hangi sınıftan türediğini bilme ihtiyacı hissediyoruz. Ayrıca gelen referansları da ait oldukları nesne türüne tür dönüşümü yaparak çeviriyoruz. Çünkü hangi nesneye ait BenKimim fonksiyonunun çağırılacağının belirlenmesi gerekmektedir.

Kalıtım nedeni ile ana sınıfta olup da yavru sınıflarda override edilmeyen birçok metod olabilir. Bu durumda ana sınıf türünden bir değişkene yavru sınıfa ait bir referansı kolaylıkla bağlayablirsiniz, bir sorun ile de karşılaşmazsınız. Metodu da rahatlıkla çağırabilirsiniz. Fakat kalıtım yolu ile yavru sınıflara iletilmeyen yeni bir metoda sahip yavru sınıfa ait referansı, ana sınıfa ait bir değişkene bağlayıp, yavru sınıfta yeni oluşturulan metodu çağırmaya kalktığınızda olanlar olacaktır. Bu bir derleme zamanı hatası oluşturur. Çünkü bu metod ana sınıfta yer almamaktadır. Polimorfizmin olduğu her yerde ana ve yavru sınıflara ait metodlar aynı olmalıdır ve her iki sınıf içerisinde de yer alıyor olmalıdır. Bu zaten polimorfizm mantığının bir gereğidir.

Çok biçimliliğin bu güzelliklerinin bir bedeli de var tabi ki az önce bahsettiğim gibi. O da performans konusunda bazı olumsuzluklara yol açması olarak gösterilebilir. Bunun nedeni ise JVM'in çalışma anında geç bağlama oluşup oluşmadığına karar verme çabası ve referansların hangi nesne türüne bağlanacağının kontrol edilmesi ve o nesne türüne bir bağlama yapılmasıdır.

Normalde bir dizi oluşturduğumuzda bu dizinin tüm elemanları oluşturulduğu nesne türünden elemanlar olmalıdır. Yani int türünde bir dizi değişken tanımlayıp bu diziye string türünden bir elemanı gönderemezsiniz. Gönderirseniz zaten hatalar karşınıza çıkacaktır. Fakat polimorfizm ile farklı türden değişkenleri bir diziye atmamız bir derece mümkün olmaktadır, eğer aralarında bir kalıtımdan söz edilebiliyor ve upcasting yapılabiliyor ise. Yani ortada bir polimorfizm var ise. Bu konuyu "Late Binding(Geç Bağlama) ve Early Binding(Erken Bağlama) nedir?" isimli yazımda daha detaylı inceledim. Çünkü olay geç bağlamaya çok güzel bir örnek. Burayı tıklayarak yazıya ulaşabilirsiniz...


PolimorfizmEdit (10.08.2017) : Aradan oldukça uzun zaman geçmiş! Yazıyı yazalı sekiz sene olmuş ve tesadüfen Google'da arama yaparken yine kendi WEB sayfama rastladım. Polimorfizmin etkisini ve anlamını anlatabilmek için çok güzel diagramlar da yapılmış aradan zaman geçtikçe. Birisini eklemeden geçemedim. Yukarıdaki yazıda bahsettiğim 'Nesnelerin gerektiğinde kılıktan kılığa girebilmesi' avantajını gösteren güzel bir figür.

Yorumlar (38) -

Gözde
Gözde
29.10.2009 06:23:09 #

upcasting yapılabilmesinin, yavru classları olustururken yanına extends ile ana class adının eklenmesiyle bir alakası var mı? yoksa orda extends yazmak ne işe yaramaktadır? Ben yeni öğrenmeye başladım da javayı. Saçma bişey sorduysam kusuruma bakmayın lütfen

Yanıtla

admin
admin Turkey
30.10.2009 15:10:31 #

Gözde selam,
Casting kavramını en genel anlamda tür dönüşümü olarak düşünebilirsin. Birçok dilde bu özellik vardır. Örneğin bir karakter değişkeni tür dönüşümü yaparak int türünden tanımlanmış bir değişkene atarak o karakterin karakter kodunu görebilirsin. Bu çok basit bir örnek ve kalıtım dediğimiz o güzel şeyden de tamamen bağımsız bir olay. Çünkü int ve char türleri arasında bir türeme ilişkisi yoktur. Dolayısıyla upcasting ve downcasting'den burada söz etmek mümkün değildir.

Ancak ve ancak birbirinden türeyen nesneler için upcasting ve downcasting'den söz edilebilir. Türemenin anahtar sözcüğü ise 'extends' kelimesidir. 'Extends' anahtar sözcüğü ile upcasting arasındaki bağı bu şekilde kurabilirsin. Eğer bir tür kendisinin türetildiği türe dönüştürülüyorsa burada bir yukarı çevrim yani upcasting vardır. Çünkü türeyen sınıf türediği sınıfa ait tüm özellikleri zaten içermektedir. Yeri geldiğinde ise türediği sınıfmış gibi davranabilmektedir.

Umarım faydalı olmuştur. Eğer eksik varsa yazmaktan çekinme.
Cem

Yanıtla

Ali Çevik
Ali Çevik Turkey
19.03.2010 11:34:02 #

Cem bey merhabalar..

Benim size bir sorum olacaktı.Makalenizi okudum.Çok yararlı olmuş.Mantığı güzel anlatmışsınız.Pekii...KISI, PERSONEL, MUHENDIS, TEKNISYEN sınıflarındaki BenKimim() metodu parametreli bir metod olsaydı(mesela BenKimim(int kişiID), kişiID yi tamamen örnek  için verdim) o zaman KimimOnuYaz() metodu içinden BenKimim() kişiID parametreli metotlarına parametreyi nerden verecektim ???

Yanıtla

admin
admin Turkey
26.03.2010 06:11:18 #

Ali selamlar,
Öncelikle yazı hakkındaki güzel yorumların için teşekkürler. Soruya gelince çok güzel bir noktaya değinmişsin. Bunun için ilk etapta iki tane basit yöntem geliyor aklıma.

1- KimimOnuYaz metodunun içerisine göndereceğin parametreyi BenKimim metodunun içerisinden yakalayabilirsin. Yani her iki fonksiyonu da parametre kabul eder hale getirirsen iş kolayca çözülür.

2- Parametreyi kullanmasını istediğin sınıf içerisinde public bir değişken oluşturarak bunu KimimOnuYaz metodunu çağırmadan önce set etmelisin. Böylece Bu değişkeni BenKimim metodu içerisinden istediğin gibi kullanabilirsin. Bu işi istediğin değişkeni setlemek için yazacağın özel bir metod ile yaparsan daha hoş olur tabi ki Smile

Bana soracak olursan 2. yöntem daha hoş olur. Böyle biraz havada kaldı sanki ama güzel bir konuya değinmişsin. Bunu örnekle pekiştirmeye çalışacağım bu yazıyı güncelleyerek en kısa zamanda Smile

Kolay gelsin...

Yanıtla

Ersoy
Ersoy Turkey
01.06.2010 13:23:19 #

ilk verdiğiniz örnek kodda hata olduğunu düşünüyorum.
public static void main(String[] args)
46.    {
47.        KISI Insan1=new KISI();
48.        PERSONEL Insan2=new PERSONEL();
49.        MUHENDIS Insan3=new MUHENDIS();
50.        TEKNISYEN Insan4=new TEKNISYEN();
51.        KimimOnuYaz(Insan1);
52.        KimimOnuYaz(Insan2);
53.        KimimOnuYaz(Insan3);
54.        KimimOnuYaz(Insan4);
55.    }

doğrusu

public static void main(String[] args)
46.    {
47.        KISI Insan1=new KISI();
48.        KISI Insan2=new PERSONEL();
49.        KISI Insan3=new MUHENDIS();
50.        KISI Insan4=new TEKNISYEN();
51.        KimimOnuYaz(Insan1);
52.        KimimOnuYaz(Insan2);
53.        KimimOnuYaz(Insan3);
54.        KimimOnuYaz(Insan4);
55.    }

olmalı,ancak bu şekilde polymorphism sağlanmış olur.
Saygılar.

Yanıtla

admin
admin Turkey
02.06.2010 12:36:26 #

Ersoy merhaba,
Aslında güzel bir noktaya basmışsın. Bunu da açıklığa kavuşturmak gerekir diye düşünüyorum. Gözde'nin sorusuna cevap verirken upcasting ve downcasting'ten bahsetmiştim. Bu yazıyı yazarken de polimorphism'in olduğu yerde upcasting de vardır diye belirtmiştim. İşte senin yazmış olduğun yorumun cevabı da upcasting de saklı. neden?

Benim yaptığım örnekte Insan2 isimli değişken PERSONEL isimli sınıfın bir nesne örneği olarak oluşturuluyor ve yine PERSONEL türünden bir nesneye bağlanıyor. PERSONEL türünden bu nesne KimimOnuYaz yordamı içerisine parametre olarak gönderildiğinde ise upcasting yapılarak KISI türünden bir nesneye bağlanmış oluyor.

Senin örneğinde ise Insan2 isimli değişken PERSONEL isimli sınıfın bir nesne örneği olarak oluşturuluyor fakat KISI türünden bir nesneye bağlanıyor. Bu sefer upcasting olayı ise tam olarak burada yapılmış oluyor. Dolayısı ile KISI türünden bu nesne KimimOnuYaz yordamı içerisine parametre olarak gönderildiğinde upcasting yapılması da gerekmiyor.

Peki şimdi soru şu "İki örnekten hangisi doğru, ya da hangisi hatalı acaba?" Cevap ise şöyle. İki örnek de doğru. Yani ikisi de polimorphism için birer örnek. Bu aşamada "... ancak bu şekilde polymorphism sağlanmış olur ..." cümlene katılmadığımı belirtmek istiyorum, zira her ikisi de yanlış değil Smile

Yorumun için teşekkür ederim,
Kolay gelsin,
Cem

Yanıtla

Şeref AKYÜZ
Şeref AKYÜZ Turkey
31.03.2011 22:34:15 #

Cem bey,

public static void main(String[] args)
46.    {
47.        KISI Insan1=new KISI();
48.        KISI Insan2=new PERSONEL();
49.        KISI Insan3=new MUHENDIS();
50.        KISI Insan4=new TEKNISYEN();
51.        KimimOnuYaz(Insan1);
52.        KimimOnuYaz(Insan2);
53.        KimimOnuYaz(Insan3);
54.        KimimOnuYaz(Insan4);
55.    }

bu işin aslı şu değil midir? Siz bağlama diye bahsetmişsiniz ama bence olay şudur: Değişken, kişi üzerinden oluşturuluyor ama hafızada personel, mühendis ve teknisyen türünden bir değişken olarak yer ayrılıyor...

Yanıtla

admin
admin Turkey
04.04.2011 04:53:02 #

Seref Selamlar,
Yok yok tam olarak benim dediğim gibi konuyu daha fazla karmaşıklaştırmaya gerek yok Smile

Yanıtla

Şeref AKYÜZ
Şeref AKYÜZ Turkey
05.04.2011 12:42:25 #

"Karmaşıklaştırmamak" adına sizin dediğiniz gibi olsun o zaman Smile Diğer arkadaşlar benim yorumumu görmezden gelsinler Smile  

Yanıtla

Berkan Bilgin
Berkan Bilgin Turkey
16.07.2010 00:06:21 #

Selamlar Cem Bey , yazmadan geçmek istemedim  , java da polymorhphism ve encapsulation hakkında bişeyler arastırıyodum fakat bi türlü anlayamıyodum,Suan Adeta beynimi aıp içine yerleştirdiniz Smile Çok ok teşekkür ederim , arkadaslarda resmen benm sormak istediğim ne varsa sormuslar, diğer arkadaşlarımada tavsie edicem , elinize emeğinize sağlık...

Yanıtla

admin
admin Turkey
16.07.2010 04:04:49 #

Berkan Bey tekrar merhaba,

Yazılarımın beğenildiğini ve fayda oluşturduğunu görmek beni çok sevindirdi. Eğer yeni öğrendiğiniz veya burada eksik bulduğunuz noktalar olursa hiç çekinmeden buradan paylaşabilirsiniz yazının diğer okurlarıyla da.

Kolay gelsin,

Cem

Yanıtla

nisnas
nisnas Turkey
18.01.2011 17:05:53 #

size teşekkur etmek istedim Smile

Yanıtla

admin
admin Turkey
18.01.2011 23:54:36 #

Ben teşekkür ederim Smile Umarım faydalı olmuştur..

Yanıtla

iverson_36
iverson_36 Turkey
20.02.2011 18:47:02 #

Öncelikle makaleniz için çok teşekkür ederim.Benim bikaç sorum olucak.Sorularımı sıralarsam;
1) Öncelikle belki makalenin konusuyla pek alakası olmayabilir ama classlarınızı neden static olarak tanımlamışsınız.Acaba class içerisinde, class tanımladığınızdan dolayı mı?Ayrıca static classların örneği oluşturulabiliyormu biraz unutmuşumdaSmile)
2)Ayrıca override ettiğimiz methodların parametreleri birbirinden farklı olabilirmi acaba.Mesela Teknisyende 2 parametre alıp,Personel 3 parametre alabilir mi?
     Son olarak Ersoy Bey'in bir yanlışlık var diyerekten gönderdiği yorumu okudum.Aslında yanlışlık yok da sizin yapmış olduğunuz örnekte KimimOnuYaz() methoduna gerek yok bence.Personel,Mühendis,Kisi classlarının nesnesini oluşturduktan sonra direk BenKimim() fonksiyonunu çağırırsanız herbiri için hepsi kendine ait BenKimim()methodunu çağırıp farklı çıktılar vericek zaten.Asıl düzgün şekli Ersoy Bey'in dediği gibi bütün türetilen classları, türediği classa ait nesneye atayıp KimimOnuYaz() methodunu kullanmayarak direk bu classlar üzerinden BenKimim() methodunu herbiri için çağırmak bence yanlışsam düzeltirseniz sevinirim.Cevabınız bekliyorum

Yanıtla

admin
admin Turkey
21.02.2011 02:39:08 #

iverson selam, Türkiye'ye hoş geldin!
Makaleyi beğenmen beni sevindirdi, umarım faydalı da olmuştur fakat çok soru sormuşsun! Onun için biraz uzun sürecek sanırım cevapları okuman Smile

Öncelikle belki makalenin konusuyla pek alakası olmayabilir ama classlarınızı neden static olarak tanımlamışsınız.Acaba class içerisinde, class tanımladığınızdan dolayı mı?Ayrıca static classların örneği oluşturulabiliyormu biraz unutmuşumda)
İlk olarak sınıfların neden static olarak tanımlandığı konusuna bir bakalım. Bu tamamen tercih meselesi ama benim static tanımlama tercihimin altında tabiki bir şeyler yatıyor. Eğer bir sınıf içerisinde başka bir sınıf tanımlarsan tanımladığın bu alt sınıfa ait nesne örneğini direk olarak tanımlayamazsın. İlk önce kapsül sınıfa(Kapsül sınıf=diğer oluşturulan sınıfları çevreleyen sınıf) ait bir nesne örneği oluşturmalı sonrasında ile alt sınıfa ait nesne örneğini oluşturman gerekir. Yani aşağıdaki gibi;

Main.KISI Insan=new Main().new KISI();

Ben bunu çok sevmiyorum, static ise beni bu örnekte kısıtlamadığı için kolay yol olan aşağıdakini kullanabilmek için böyle bir yöntem seçtim. Bu benim tercihimdir ve öneririm.

KISI Insan=new KISI();

Fakat burada önemli bir noktaya dikkat etmelisin. Static tanımlanan tüm sınıflar kapsül sınıf ile aralarındaki "this" ilişkisini kaybederler. Yani sen kapsül sınıf içerisinde her hangi bir değişken tanımlasaydın bu değişkene static sınıf örneğin içerisinden kesinlikle ve kesinlikle erişemeyecektin. Benim örneğimde böyle bir olasılık ve gereksinim bulunmadığı için bir sakınca yok Smile

Ayrıca override ettiğimiz methodların parametreleri birbirinden farklı olabilirmi acaba.Mesela Teknisyende 2 parametre alıp,Personel 3 parametre alabilir mi?
Gelelin ikinci soruya. Override etmek demek aynı özellikli fonksiyonları ezmek demektir. Yani sen eğer Teknisyen'de iki, Personel'de üç parametre içeren foksiyonlar yazarsan onlar artık başlı başına yeni fonksiyonlar olmuş olur. Yani burada bir override söz konusu değildir. ana sınıftaki fonksiyonu korumuş olursun, ayrıca yavru sınıf içerisinde de aynı isimli fakat farklı parametreler alan yeni bir fonksiyon oluşturmuş olursun.

Son olarak Ersoy Bey'in bir yanlışlık var diyerekten gönderdiği yorumu okudum.Aslında yanlışlık yok da sizin yapmış olduğunuz örnekte KimimOnuYaz() methoduna gerek yok bence.Personel,Mühendis,Kisi classlarının nesnesini oluşturduktan sonra direk BenKimim() fonksiyonunu çağırırsanız herbiri için hepsi kendine ait BenKimim()methodunu çağırıp farklı çıktılar vericek zaten.Asıl düzgün şekli Ersoy Bey'in dediği gibi bütün türetilen classları, türediği classa ait nesneye atayıp KimimOnuYaz() methodunu kullanmayarak direk bu classlar üzerinden BenKimim() methodunu herbiri için çağırmak bence yanlışsam düzeltirseniz sevinirim.
Burada Ersoy'a yazmış olduğum cevaba dikkat ettin mi tam olarak çıkaramadım, asında orada onun için gerekli cevabı vermiştim. Senin bahsettiğin konu ise Ersoy'un bahsettiğinden çok daha farklı bir noktada aslında. Ersoy polimorphism ile ilgili bir soru sormuştu ama sen polymorphism konusunu tam anlayamadığın için farklı bir noktaya değinmişsin. Şimdi bu fırsatla tekrar değinmek istiyorum. Burada amacımız BenKimim() fonksiyonunu doğrudan çağırıp da işlem yaptırmak değil. Burada amacımız kalıtım ve kalıtımın beraberinde getirdiği bir güzellik olan çok biçimliliği uygulamak. Onun için parametre olarak KISI türünden bir nesne kabul eden fonksiyon içerisine KISI'den türeyen Personel, Mühendis ve Teknisyen türünden değişkenleri giriş olarak veriyoruz. Böylece çok biçimliği sağlamış oluyoruz. Yani Ersoy ile senin bahsettiğin noktalar birbirinden tamamen alakasız. Bu bağlamda KimimOnuYaz() metoduna gerek var mı? Evet fazlasıyla gerek var Smile

Umarım cevaplar anlaşılır olmuştur iverson, şimdi ben senin dönüşünü bekliyorum Smile

Teşekkürler,
Cem

Yanıtla

iverson_36
iverson_36 Turkey
21.02.2011 15:37:10 #

Uzun uzun cevap yazmışsınız cidden çok teşekkür ederim Özellikle static konusunu öğrendim sayende.Override sorusunu sorduktan sonra düşündüm olmayacağını bende anladımSmileSon soruma verdiğin cevaba karşılık şunu söyliyim.Polimorfizmi zaten biliyordum senin sayendede iyice anladım.Tamam KimimOnuYaz() methodunu çıkarırsak sizin örneğinizde polimorfizm diye birşey olmuyor.Ama aşağıdaki gibi yaparsak da polimorfizm oluyor.Asıl sorum aşağıda yazdığım kodda geç bağlama olayı varmı vede polimorfizm söz konusu olduğunda illaki geç bağlama olayı da gerçekleşiyormu.Tahminimce gerçekleşiyorSmile)
public static void main(String[] args)
    {
        KISI Insan1=new KISI();
        KISI Insan2=new PERSONEL();
        KISI Insan3=new MUHENDIS();
        KISI Insan4=new TEKNISYEN();
     Insan1.BenKimim();
     Insan2.BenKimim();
...
}

Yanıtla

admin
admin Turkey
22.02.2011 11:24:35 #

Rica ederim iverson. Son durumu şu şekilde özetlemeye çalışayım;

Geç bağlama(Late Binding) kavramı ile çok biçimlilik(Polimorphism) adeta iç içe geçmiş kavramlardır. Çok biçimlilik ile de kalıtım(Inheritance) iç içe geçmiş iki kavramdır. Kalıtım olmadan çok biçimlilikten bahsetmek imkansızdır. Bir başka söyleyişle çok biçimlilik kalıtımın doğal bir sonucudur. Çok biçimlilik olmadan da geç bağlamadan söz etmek anlamsızdır. Yani geç bağlama da çok biçimliliğin doğal bir sonucudur ve çalışma anında(Run Time) bir anda kendisini gösteriverir. Eğer polimorfizme çalışma anında karar verilirse burada geç bağlamadan söz etmek daha mantıklıdır.

Yukarıdaki birkaç cümle aslında kafanda olayı netleştirmiştir diye düşünüyorum. Geç bağlama ile ilgili daha dataylı bir makeleme buradan(http://www.cemkefeli.com/post/2009/09/29/JAVA-Late-Binding%28Gec-Baglama%29-ve-Early-Binding%28Erken-Baglama%29-nedir.aspx) ulaşabilirsin, umarım bu da faydalı olur. Ama biraz daha açarsak;

Benim verdiğim örnekte yalnızca Insan1 isimli nesne ana sınıfa(Base Class) ait bir nesne örneğidir. Diğerleri(Insan2, Insan3 ve Insan4) ise türeyen sınıfların(Derived class) birer nesne örneğidir. Polimorfizmden bahsedebilmemiz için arada bir dönüşüm(Casting) operasyonunun olması şart. Zaten polimorfizmde de yukarı dönüşüm(Upcasting) olduğu için geç bağlama olayı gerçekleşmiş olur. Peki nasıl olur bu iş? Tam da KimimOnuYaz çağrıldığında bu olay gerçekleşmiş olur, çok biçimlilik de geç bağlama da tam da buradadır. Çünkü bu fonksiyon KISI türünden nesne örneklerini kabul ettiği halde biz ona türeyen sınıfa ait bir nesne örneğini al bunla işlem yap diyoruz.

Şimdi senin örneğine gelecek olursak;
Bu sefer sonuca bir öncekinden bir adım daha fazla yaklaşmışsın. PERSONEL türünden bir nesne örneğini KISI türünden Insan2 değişkenine bağlamışsın. Peki polimorfizm nerde? İşte tam da o noktada. Yani bu durum Ersoy'un bahsettiği duruma çok benziyor. Ona da verdiğim cevaptaki gibi bu farklı şekillerde yapılabilir ve doğru/yanlış diye değerlendirilemez. Çünkü hepsi doğru! Fakat Insan1 için aynısını söylemek mümkün değil. Burada hem Insan1 in tanımlanması ve nesne örneği bağlanması aşamasında hem de BenKimim fonksiyonunun çağırılması aşamasında bir polimorfizmden bahsetmek söz konusu değildir. Çünkü hem nesne türü hem de nesne örneği türü aynıdır ve bir casting söz konusu değildir.

Umarım anlaşılmıştır söylemek istediklerim.

Bir soru da benden Smile Cevap yazdığım yorumdan ne şekilde haberdar oldun? "Yeni yorum eklendiğinde beni haberdar et" sayesinde mi? Bazen bu fonksiyonda problemler çıkıyor da takip etmek istiyorum.

Teşekkürler,
Cem

Yanıtla

iverson_36
iverson_36 Turkey
22.02.2011 11:48:05 #

Cevabın için teşekkürler.Bilgilerimi teyit ettirdim sayendeSmileYok ben direk sayfayı sık kullanılanlara ekleyip bakiom.Senin Haberdar et butonu çalışmıyorSmile)Mail atiyon herhalde.smtp,pop adreslerin yanlıs olabilir.

Yanıtla

admin
admin Turkey
22.02.2011 23:16:35 #

Var bir tuhaflık.. relay de sorun yok ama ne hikmetse bazen takılıyo kafasına göre.. Bi yerlerden exception filan mı alıyo ne..Smile  Bakıcam ama buna..

Yanıtla

efe
efe Turkey
05.03.2011 02:13:45 #

her yerde polimorfizm anlatılmış ama senin sayende anladım şu mereti. 2'inci örnekten if controllerini görünce neden polimorfism varmış anladım Smile çok tşk ederiz

Yanıtla

admin
admin Turkey
05.03.2011 05:38:05 #

Smile Rica ederiz.. Faydalı olduğunu görmek güzel..

Yanıtla

Şeref AKYÜZ
Şeref AKYÜZ Turkey
31.03.2011 22:44:53 #

Teşekkürler güzel örnekler, p.tesi sınavım vardı konuyu daha iyi anlamamı sağladı yazınız. Kolay gelsin...

Yanıtla

serdar
serdar Turkey
07.04.2011 15:18:16 #

çok güzel ve açıklayıcı bir makale olmuş emeğinize sağlık

Yanıtla

admin
admin Turkey
08.04.2011 04:10:59 #

Teşekkür ederim Serdar,

Yanıtla

emre
emre Turkey
08.05.2011 12:52:49 #

çok teşekkürler sayfalarca java how to program kitabına bedel anlatımınız

Yanıtla

admin
admin Turkey
08.05.2011 23:46:35 #

Çok tşekkür ederim Emre, vakit bulabilsen daha da yazacam, kendim de unutup burdan bakıyorum çünkü Smile

Yanıtla

BURAK
BURAK Turkey
27.12.2011 07:06:09 #

Merhaba, Emeğinize sağlık, Çok güzel bir makale olmuş.
Uzun bir süredir oop ile ugraşmıyordum. Şimdi başladım tekrar.
Kafama takılan bişey oldu örneklerde New Keyword u ile nesne oluşturmada.

PERSONEL  insan = new PERSONEL();
ile
KISI insan = new PERSONEL();  arasında ne fark var?
Personel zaten kişiden türeyen bir sınıf degilmi, neden kisi insan=new denilmesi gerekiyor burada?
Kisi insan = new PERSONEL(); demek tam olarak ne demek oluyor? insan değişkeni burada Personele mi yoksa kisi ye mi dünüşüyor. sağdan sola yada soldan sağa kod satırını okup yorumlarmısınız lütfen?

Yanıtla

admin
admin Turkey
09.10.2012 06:52:03 #

Burak Merhaba,
Biraz da geç cevap olmuş ama Smile tam olarak anlayamadım soruyu. Biraz daha açabilir miyiz?

Teşekkürler,
Cem

Yanıtla

ilker_sinan
ilker_sinan Turkey
17.01.2012 06:45:06 #

merhaba Cem bey,
öncelikle siteniz gerçekten çok yararlı.Polymorpism konusunu anlamk için kodları inceledim mantığıda kavradım sayılır ama bir sıkıntı varSmile
ben abstract SHAPE classı,shape ten türeyen kare ve üçgen classları yarattım.
her class a da kendine özgü alanı hesaplayan area fonk yazdım.
test classım(main olan) da da alanıHesapla fonk yaratım parametre olarak SHAPE shape1 verdim.
ancak program hata veriyor. kare de 1 , ucgen objesinde 2 parametre var(yükseklik ekledim)
nedendir acaba main de tekrar bişiler mi tanımlamak gerekiyor .cevaplarsanız çok sevinirim.

Yanıtla

admin
admin Turkey
17.03.2012 02:05:09 #

İlker Selamlar,
Bir süre önce web sitem çöktü ve ilgilenemedim ancak cevap yazıyorum. Eğer kodu gönderebilirsen bakmak isterim.

Teşekkürler,
Cem

Yanıtla

ResulRzayev
ResulRzayev Azerbaijan
25.08.2012 04:15:04 #

Oncelikle Azerbeycandan selamlar saygilar .Verdiginiz egitimsel icerikli yazilarinizi cok  begendim yararli mekaleler hakkaten.Benim sorum Design Patterne uygun olarak Polymorphism-den ne zaman kullanmak daha dogrdudur .Meslela gelecekde degistirilecek metodlar falan varsa intefaceden istifade ediyoduk peki polymorphism ne zaman daha kullanisli ?  umarim anlata bilmisimdir .Kardeslerime saygilar ve sevgiler !

Yanıtla

admin
admin Turkey
09.10.2012 06:44:50 #

Selam ResulRzayev, soruyu biraz daha açabilir miyiz acaba? Smile

Yanıtla

murat
murat United States
22.09.2012 02:54:32 #

Bence de hata var. Doğrusu:
public static void main(String[] args)
    {
        KISI Insan1=new KISI();
        KISI Insan2=new PERSONEL();
        KISI Insan3=new MUHENDIS();
        KISI Insan4=new TEKNISYEN();
     Insan1.BenKimim();
     Insan2.BenKimim();
...
}

Yanıtla

admin
admin Turkey
10.10.2012 01:02:25 #

Selam Murat,

'Bence de hata var....' yazmışsın ama nerede hata var anlamadım ben... Smile Açabilir miyiz? Eğer casting'den bahsediyorsan doğru/yanlış diye birşey yok. Senin yazdığın da olur benim yazdığım da... Yukarılarda bir yerde tartışılmıştı bu konu daha önce...

Teşekkürler,
Cem

Yanıtla

Fatih OKUTAN
Fatih OKUTAN Turkey
22.09.2012 12:18:12 #

Nesneden nesne türetmek diye bir kavram var mı ? Yoksa doğrusu sınıftan sınıf türetmek midir ?

Yanıtla

admin
admin Turkey
08.10.2012 01:36:16 #

Fatih Merhaba,

Aslında doğrusu sınıf'tan sınıf türetmek... Nesne zaten sınıfların birer örneğidir.. Yani bizim yazdığımız sınıftan new keywordü ile bir  şey türettiğimizde onun adı nesne oluyor. Aslında makaleleri yazarken bu detaya (ki çok önemli bir detay aslında) dikkat ettim mi bilemedim, tüm yazıları baştan bir kontro edeceğim...

Teşekkürler,
Cem

Yanıtla

DEMET
DEMET
30.11.2016 13:23:25 #

makaleniz için çok teşekkürler benim de 2 sorum var yardımcı olursanız çok sevinirim.
1.static public class TEKNISYEN  extends PERSONEL
  {
    @Override
    public void BenKimim()
    {
      System.out.println("Ben bir teknisyenim.");
    }
  }
burada PERSONEL i extend etmişiz neden MUHENDİS i etmedik çoklu kalıtımı implement ile yapmıyormuyduk.
2.yukarıda bi arkadaş da sormuş KISI Insan2=new PERSONEL(); ile PERSONEL Insan2=new PERSONEL(); arasında ne fark var

Yanıtla

Cem
Cem
01.12.2016 00:21:06 #

Demet merhaba,

Aslında buradaki kod parçacıkları tamamen çok biçimliliği anlatabilmek için vermiş olduğum birkaç örnekten ibaret. Yani aslında bu örnek, TEKNISYEN ve MUHENDIS sınıflarının PERSONEL sınıfından, PERSONEL sınıfının ise KISI sınıfından türediğini, aralarında kalıtımsal bir bağ olduğunu göstermek için oluşturulmuştu.

Bu açıklamayı dikkate alacak olursak, sınıflar arası kalıtımsal ilişkiyi görmüş oluruz. Bu yüzden TEKNISYEN ve MUHENDIS sınıfları PERSONEL sınıfından türeyecektir. Yazı içerisindeki UML diagramında bu durumu görebiliyoruz. İlk sorun için bu şekilde cevap verebilirim. Kaldı ki burada zaten çoklu kalıtım yapısı bulunmuyor.

İkinci sorunun cevabı ise, yine örneğin oluşturulma amacıyla ilgi. Bu örnekteki amacımız çok biçimliliği göstermek olduğu için ve KimimOnuYaz fonksiyonu da KISI türünden sınıfları kabul ettiği halde nasıl oluyor da KISI sınıfından değil de diğer sınıflardan parametre kabul edebiliyor ve derleme sırasında hata da vermiyor sorularını gözler önüne serebilmek amacıyla bu şekilde bir tanımlama yapılmıştı.

Umarım açıklayıcı olmuştur. Eğer soru varsa devam edebiliriz.

Teşekkür ederim.

Yanıtla

Yorum ekle

biuquote
  • Yorum
  • Canlı önizleme
Loading

Hakkımda...

Cem KEFELİ

Electronics and
Telecommunication Eng.
devamı...


Son yapılan yorumlar...

Comment RSS

Yasal bir uyarı...

Disclaimer"Bu web sitesinde görmüş olduğunuz bilgilerin, dokümanların ve diğer materyallerin kullanılmasından doğabilecek hiç bir sorumluluktan site sahibi sorumlu tutulamaz. Web sitesi içerisinde yer alan yazılar, yorumlar, resimler ve diğer tüm içerikler yalnızca sahibinin görüşünü yansıtmakta olup içeriğin sahibi kişilerin çalıştığı kurumları bağlayıcı hiç bir nitelik taşımamaktadır. Yapılan tüm alıntılar mutlaka kaynak gösterilerek verilmeye çalışılmaktadır. Web sitesi içerisinde bulunan ilgili materyaller, ilgili yasal kurumlar tarafından uygun görülmemesi durumda kaldırılacaktır."
General