220 likes | 439 Views
Nesneye Dayal ı Programlama. DERS 7. POLYMORPHISM ( Çok Şekillilik ). Nesneye Dayalı Programlamanın üç önemli kavramı vardır: 1.Sınıflar 2.Türeme(Miras) 3.Çok Şekillilik(C++’daki sanal fonksiyonlar tarafından gerçekleştirilir)
E N D
Nesneye Dayalı Programlama DERS 7 Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
POLYMORPHISM(Çok Şekillilik) • Nesneye Dayalı Programlamanın üç önemli kavramı vardır: 1.Sınıflar 2.Türeme(Miras) 3.Çok Şekillilik(C++’daki sanal fonksiyonlar tarafından gerçekleştirilir) Gerçek hayatta, aynı komutu(mesajı) alan yanlız buna farklı şekillerde cevap veren pek çok nesne vardır. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Yönetici ve öğretmen örneğini ele alalım. • Örneğin Milli Eğitim Bakanı bütün personele ‘kişisel bilgilerinizi yazdırın’ diye bir direktif veriyor. • Değişik türde personel, değişik bilgi verecektir. Fakat bakanlığın her biri için ayrı direktif vermesine gerek yoktur.Bir mesaj hepsi için geçerlidir, çünkü bütün personel kişisel bilgilerini nasıl yazdırmaları gerektiğini bilmektedir. • Ayrıca bakanlığın, direktifin gittiği personelin de ne tür bir çalışan olduğunu bilme zorunluluğu yoktur. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Polymorphism “çok şekil alabilmek” demektir. Bakan’ın direktifi polimorfiktir çünkü her çeşit personele farklı gözükmektedir. Ayrıca bakan mesajı gönderdiği personelin öğretmen yada müdür olup olmadığını bilmek zorunda değildir. • Aynı şekilde, Polymorphism miras yoluyla birbiriyle ilişkilendirilmiş sınıflardada meydana gelir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
C++’da polymorphism mesajı alan farklı türde nesnelerin farklı fonksiyonlar çağırmasına neden olacak üye fonsiyon çağırmaya denir. • Mesajın göndericisinin,mesajı alan nesnenin türünü bilmesi gerekmemektedir. • Kulağa biraz overloading olayı gibi gelsede polymorphism daha degişik ve güçlü bir mekanizmadır. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Pointerlar tarafından erişilebilen normal üye fonsiyonlar • Aşağıdaki örnekte, taban ve türemiş sınıflarda aynı isimlerde fonksiyonlar bulunduğu zaman ve pointer kullanarak sanal(virtual) fonksiyonlar olmadan bu fonksiyonlara erişilmeye çalışıldığı zaman ne olacağı gösterilmektedir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
ÖRNEK 1: class Teacher{ // Taban sınıf string *name; int numOfStudents; public: Teacher(const string &, int); // Taban sınıf kurucusu void print() const; }; class Principal : public Teacher{ // Türemiş sınıf string *SchoolName; public: Principal(const string &, int , const string &); void print() const; }; • Her iki sınıfın da print adında bir fonksiyonu vardır. Fakat bu örnekte bu fonksiyonlar sanal(polimorfik) değildir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
void show (Teacher * tp) { tp->print(); // yazdırma } // show fonksiyonunu test etmek için yazılmış main program int main() { Teacher t1("Teacher 1",50); Principal p1("Principal 1",40,"School"); Teacher *ptr; char c; cout << "Teacher or Principal "; cin >> c; if (c=='t') ptr=&t1; else ptr=&p1; show (ptr); // which print return 0; } Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Principal sınıfı Teacher sınıfından türemiştir. İki sınıfında print() isminde üye fonksiyonu vardır. • Main() de, program Teacher ve Principal sınıflarının birer nesnesini ve Teacher sınıfına bir pointer oluşturur. • Main program bazen teacher nesnesinin bazen de türemiş sınıf nesnesinin(Principal) adresini taban sınıf pointerına koyar: ptr = &p1; Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Hatırlayalım ki Türemiş nesnenin adresi taban sınıfın pointerina verilebilir. Bu adres show() fonksiyonunda,pointer vasıtasıyla tabana gönderilebilir. • Taban sınıftaki(Teacher) fonksiyon her iki durumda da çağırılmıştır. Derleyici pointerin içeriğini(ptr) görmezden gelir, pointerla aynı türü tutturan üye fonksiyonu seçer. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Pointerlarla Erişilebilen Sanal Üye Fonksiyonlar • Programda küçük bir değişiklik yapalım.Taban sınıftaki print() fonksiyonunun prototipinin önüne virtual kelimesini koyalım. ÖRNEK 2: class Teacher{ // taban sınıf string *name; int numOfStudents; public: Teacher(const string &, int); // taban sınıf kurucusu virtual void print() const; // sanal (polymorphic) fonksiyon }; class Principal : public Teacher{ // turemis sınıf string *SchoolName; public: Principal(const string &, int , const string &); void print() const; // dolayısıyla bu da sanal (polymorphic) }; Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Bu örnekte, ptr’nin içeriğine göre değişik fonksiyonlar çalıştırılmıştır. • Fonksiyonlar pointerın türüne göre değil, içeriğine göre çağırılmıştır. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Çok Şekillilik(Polymorphism)’in Yararları • Esneklik sağlar. • Bizim örneğimizde show(), girdi parametresinden nesnenin türüyle ilgili bilgi almamıştır. Teacher sınıfından türemiş herhangi bir nesnenin adresini alabilir. • Yani bu fonksiyon Teacher sınıfından türemiş bütün sınıflarla çalışabilir. • Eğer programa başka bir öğretmen türü(başka bir sınıf) eklersek, örneğin InternTeacher, show() fonksiyonunu değiştirmemize gerek yoktur. • Aynı şey, programdan Teacher sınıfından türemiş başka bir sınıfı çıkarmak istediğimiz zamanda geçerlidir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Şunu unutmayalım ki, C++’da parametreyle pointer göndermektense, referans göndermek tercih edilir. • Aynı program aşağıdaki gibi yazılabilir: void show (const Teacher & tp) { tp.print(); // which print } int main() { Teacher t1("Teacher 1", 50); Principal p1("Principal 1", 40, "School"); char c; cout << "Teacher or Principal " ; cin >> c; if (c == 't') show(t1); else show(p1); : Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Late Binding(Geç Bağlama) • Derleyici hangi fonksiyonu derlemesi gerektiğini nerden bilecektir? Birinci örnekte, polymorphism olmadan, derleyici tp->print(); ifadesiye ilgili bir sorun yaşamamaktadır. • Her zaman taban sınıfın print() fonksiyonunu çağırarak derleme yapmaktadır. • Ancak ikinci örnekte derleyici, tp’nin içeriğinin hangi sınıfa işaret ettiğini bilmemektedir. Teacher yada Principal sınıflarında herhangi birinin nesnesinin adresi olabilir. Derleyici hangi print()’i çağıracak. Gerçekte, derleme esnasında, derleyici hangi programı çağıracağını bilmez, onun yerine oraya kod parçası yerleştirir. • Yürütme sırasında, foksiyon bildirimi çalıştırıldığı zaman, derleyici tarafından yerleştirilen kod, tp’nin içinde adresi olan nesnenin çeşidini bulur ve uygun print() fonksiyonu çalıştırır. Teacher::print() veya Principal::print(). Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Fonksiyonun yürütme esnasında belirlenmesine late binding veya dynamic binding denir.(Binding fonksiyon çağırımıyla fonksiyonu birleştirmek demektir). • Fonksiyonlarla normal şekilde birleştirmeye early binding veya static binding denir. • Late binding diğerinden daha fazla zaman alır, ancak programa güç ve esneklik sağlar. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Nasıl Çalışır? • Hatırlayalımki, hafızada saklanan normal bir nesne(sanal fonksiyonu bulunmayan), sadece kendi verilerini içerir. • Üye fonksiyon böyle bir nesne için çağırıldığı zaman, derleyici fonksiyonu çağıran nesnenin adresine geçer. • Bu adres, fonksiyon için this’in içinde tutulmaktadır,fonksiyon bu adresi nesnenin verilerine ulaşmak için kullanmaktadır. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
This’in içinde bulunan adres, her üye fonksiyon çağrımında derleyici tarafından otomatik olarak üretilir. • Nesne içerisinde tutulmaz ve hafızada yer kaplamaz. • This pointeri nesneyle, normal nesne fonksiyonları arasında bağlantıyı sağlayan tek şeydir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Sanal fonksiyonlarla herşey daha karmaşık bir hal alır. • Sanal fonksiyonlarla türemiş bir sınıf tanıtıldığı zaman, derleyici fonksiyon adreslerinin tutulduğu bir sanal tablo oluşturur.ikinci örnekte Teacher ve Principle sınıflarının herbirinin kendi sanal tablosu vardır. • Her sanal tabloda her bir sanal fonksiyon için giriş vardır. • Sanal fonksiyon içeren sınıfların nesneleri sınıfın sanal tablosuna işaret eden bir pointer içerir. • Bu nesneler normal nesnelerden biras daha büyüktür. • Örnekte; sanal bir fonksiyon Teacher ve ya Principle nesnesi için çağırıldığı zaman, derleyici hangi fonksiyonun çağırılacağını belirlemek yerine, nesnenin sanal tablosuna bakan ve daha sonra bunu kullanarak uygun üye fonksiyonun adresine erişimi sağlayan bir kod üretir. Dolayısıyla, sanal fonksiyonlar için, derleyici yerine nesnenin kendisi hangi fonksiyonu çalıştıracağına karar verir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
class Teacher{ // Taban sınıf string *name; int numOfStudents; public: virtual void read(); // Sanal fonksiyon virtual void print() const; // Sanal fonksiyon }; class Principal : public Teacher{ // Türemiş sınıf string *SchoolName; public: void read(); // sanal fonksiyon void print() const; // sanal fonksiyon } ÖRNEK 3: Teacher ve Principle sınıflarının her ikisininde 2 sanal fonksiyon içerdiğini varsayalım. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Teacher ve Principle sınıflarının nesneleri kendi sanal tablolarına erişebilmek için pointer içerirler. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli
Bunu nesnelerle denemeyin • Sanal fonksiyon mekanizması sadece nesne pointerları ve referanslarla çalışır, nesnelerin kendisiyle değil. int main() { Teacher t1("Teacher 1", 50); Principal p1("Principal 1", 40, "School"); t1.print(); // polymorphic değil p1.print(); // polymorphic değil return 0; } Sanal fonksiyon çağırımı, tablolarla direk olmayan çağırımlar olduğu için zaman kaybettiricidir. Harran Üniversitesi Bilgisayar Mühendisliği Yrd.Doç.Dr.Nurettin Beşli