Nesne Yönelimli Programlama – 8- Abstract Class

Merhaba yazılım dostları. Nesne Yönelimli Programlama makale serisine (keşke tüm hızıyla diyebilseydim ama, kaplumbağa yavaşlığıyla) devam ediyoruz.

Tecrübeyle sabittir ki; nesne yönelimli programlama tekniği öğrenilirken zihinde canlandırılması en güç kavramlardan biri, bu abstraction kavramıdır. Ama biliyorsunuz; yazılımda varolan herşey, günlük hayattan alıntıdır. O zaman abstract class kavramına da bu açıdan yaklaşacağız demektir. Hemen bu noktada basit bir örnekle ortamı şenlendirelim; bir markete girdiniz ve kasiyere yaklaştınız ve şöyle dediniz: “merhaba, bir ürün alabilir miyim lütfen?”. O anda kasadaki kişinin yüz halini gözünüzün önünde canlandırın lütfen. Sonra da size ne tepki vereceğini… “Hö? Ne ürünü?” Bu tepki çok normal, çünkü siz bir market için gayet ‘soyut’ bir şey istediniz. Ürün, markette satılan malzemelerin tümüne verilen genel addır ancak elinizde tutacağınız sabit bir nesne değildir. En nihayetinde siz, gazete ürünü, sakız ürünü alabilirsiniz fakat “ürün” isminde fiziksel bir nesnenin varlığı söz konusu olamaz. İşte size, abstract (soyut) sınıf kavramını anlatmış bulunuyorum; kendisinden nesne üretilemeyecek, yalnızca miras verebilecek sınıflar; abstract sınıflardır.

İşte o bomba soruyu duyar gibiyim şimdi; “iyi de ben nerede ihtiyaç duyarım soyut sınıfa?” Beyler bayanlar, aşkı yazılım olanlar; benim amacım da bunu anlatmak zaten!

Şöyle düşünün sevgili dostlarım; bir sınıf yazıyorsunuz ve bu sınıfın özelliklerinden (property) biri, başka bir nesne döndürüyor. Bu nesne de, davranışsal olarak bir kaç türe ayrılabiliyor. Bu durumda hepsini ortak bir noktada buluşturmanız şart demektir.

Biliyorum biliyorum. Bu cümle biraz karışık geldi. En iyisi örneklendirmek. Bir müzik simülatörü yazmaya karar verdiniz. Bu uygulamada kullanıcı, çeşitli müzik enstumanları kullanan müzisyenler oluştururarak bir nevi orkestra yaratır ve belirli müzikleri çalmalarını sağlar.

Böyle bir uygulamanın en önemli sınıfı, elbette Muzisyen sınıfı olacaktır. Kodlayalım öyleyse (bu örnekte modellemenin ön plana çıkması için Console Application kullandım):

Dikkat edecek olursanız, Muzisyen sınıfımızda bulunan “CaldigiEnstruman” özelliği MuzikAleti sınıfının bir nesnesini döndürüyor. Bunun nedeni, söz konusu nesnenin işlevsel açıdan uygulamanızda önemli bir yere sahip olması. Örneğin; söz konusu simülasyonda müzisyenimiz, çaldığı enstrumana göre sahnede yerini alacak. Bu durumda, burada bir miras kavramının (inheritance) kokusunu alıyor olmalısınız. Çünkü; bateri çalan müzisyen sahnenin bir yerinde, elektro gitar çalan müzisyenimiz başka bir yerinde olacağına göre, bu enstrumanların hepsi bir base class’tan türemiş olmalıdır . Haliyle, burada base class’ımız da MuzikAleti oluyor. Fakat dikkat edin; müzisyenlerinizden hiçbiri “müzik aleti” isminde bir alet çalamaz. Demek ki yazımın başında belirttiğim “market-ürün” örneğiyle karşı karşıyayız; MuzikAleti sınıfından başka sınıflara miras verilebilir ama kesinlikle nesne üretilemez. Kısacası MuzikAleti sınıfı kesinlikle abstract bir sınıf olacaktır.

Gelelim MuzikAleti sınıfının detaylarına;

Şimdi bir düşünelim; bir orkestrada olabilecek tüm müzik aletlerini gözünüzün önüne getirin. Tümünde varolan ortak metodları düşünün lütfen… Mesela Çal metodu hepsinde ortaktır öyle değil mi? Madem öyle; bu metodun, MuzikAleti sınıfının bir üyesi olması gerekiyor..

Peki Cal() metodunuzu MuzikAleti sınıfına yazıyorsunuz. Ama metod gövdesinde ne yazacaksınız? Yani MuzikAleti sınıfından sadece miras alınacağına göre; Cal() isimli metodunuz da tüm türetilen sınıflara aktarılacağına göre hangi müzik aletinin çalınma şeklini anlatacaksınız bu metodda? Diyelim ki piyanonun çalma şeklini yazdınız metod gövdesine. O zaman MuzikAleti sınıfından türeyen Gitar sınıfının da Cal() metodu piyano gibi çalınacak!

Bu sitenin takipçileri veya object oriented kavramlarını bilen arkadaşlar burada polymorphic bir metoddan bahsettiğimi anlamışlardır. Ancak, buradaki Cal() metodu virtual anahtar kelimesi ile imzalanamaz. Çünkü virtual derseniz türetilmiş sınıfta override demek ZORUNDA DEĞİLSİNİZ. Oysa bizim örneğimizde Cal() metodu hemen hemen her türetilmiş sınıfta farklı olmak zorundadır ve mecburen Override edilmesi gerekmektedir. Öyleyse bu Cal() metodu da abstract bir metoddur:

Hemen tekrar edeyim: virtual anahtar kelimesi, “bu metod ezilebilir” derken, abstract kelimesi “bu metodu ezilmek zorundadır” der. Dikkat ederseniz, abstract Cal() metodunun bir gövde kodu olmadığını görürsünüz. Anlamı çok basittir: “Cal() metodunun nasıl çalışacağını, MuzikAleti sınıfından türetilmiş sınıf belirler. ”

Aslında bu noktada msdn’den bir alıntı yapmak uygun olabilir; “abstract metodlar; gövde kodları türetilmiş sınıflar tarafından tamamlanacak olan eksik bırakılmış metodlardır”.

Bakalım Visual Studio IDE’si bir abstract sınıftan bir sınıf türetirken bize nasıl yardımcı oluyor:

 

“Implement ediim mi abü?” şeklinde türkçeye çevirebileceğimiz bu yardımsever teklife sıcak baktığımızı ifade etmek için seçeneğe tıkladığımızda bakın ne oluyor:

İşte! Ne demiştim, abstract metodlar; türetilmiş sınıflar tarafından override edilmek zorundadırlar. Şimdi siz, gitara özel cal() metodunu yazabilirsiniz:

 

Ben biraz daha örneklendireyim:

Unutmadan belirtelim; eğer class diyagramdan bakacak olursanız, abstract sınıflar, çizgili çerçeve içinde gösterilirler.

Pekala; gelin şimdi, senaryomuza göre programımıza son şeklini verelim.

Ve sonuç:

Evet sevgili dostlarım. Nesne Yönelimli Programlama konusunun bu 8. Makalesini de burada bitirmiş olduk. Bir sonraki makalede görüşmek dileğiyle.

2 thoughts on “Nesne Yönelimli Programlama – 8- Abstract Class

Leave a Reply