OOP: Polimorfizm
Kapsülleme ve kalıtım konularından sonra sıra geldi polimorfizme. Polimorfizm, Türkçe’de çok biçimlilik olarak çevriliyor. Polimorfizmi anlatmak için JUnit in Action kitabında gördüğüm güzel bir örneği vereceğim. Bu örnek sayesinde polimorfizm’in kullanım amacını da göstermiş olacağım. Örnek göstererek anlatmayı daha uygun buldum. Ben önce örnekleri inceleyip sonra açıklamaları okurdum. Bu sayede daha kolay kavrıyorum. Aynı yöntemi burda da uygulayacağım. Bu konuyu kavramanız için kalıtım konusuna hakim olmanız gerekmektedir.
Örneğimizde bir yazıcımız var. Bu yazıcı kelime işlemci ve pdf belgelerini basabiliyor.
PDF ve Word sınıfları getPrintableText() isimli bir metodu içeriyor. Şimdi de yazıcı (Printer) sınıfımıza bakalım.
Printer sınıfımızın ise iki metodu var. printPDF metodu PDF dökümanını, printWord metodu ise word dökümanını yazdırıyor. Bu metodlar bu nesneleri parametre olarak alıp, PDF ve Word sınıflarının getPrintableText metodunu kullanarak ekrana yazabiliyor.
Bu tasarım başlangıçta güzel gözükse de aslında bir çok problemi beraberinde getiriyor. printPDF ve printWord metotları nerdeyse birbirinin aynısı. Yani duplicated kod barındırıyor. Diğer bir problem diyelim ki müşteriniz Excel tablolarını da yazdırmak istedi. Ne yapmanız gerekiyor. Öncelikle bir Excel sınıfı ekleyip ardından Printer sınıfına printExcel() adlı yine aynı işi yapan bir metot eklemeniz gerekiyor. Bu sefer üç tane metod aynı işi yapmış olacak. Yer yeni bir belge türü eklediğimizde Printer sınıfını sürekli değiştirmemiz gerekiyor. Bu durum Open-Close (Açık-Kapalı) prensibine aykırı bir durum. Open-Close prensibi yazdığımız sınıfların gelişime açık fakat değişime kapalı olması gerektiğini tanımlar. Bu durumu polimorfizm ile düzeltebiliriz.
Öncelikle daha önceden öğrendiğimiz kalıtımı(yemek tarifi gibi oldu :)) kullanarak sınıflarımızı yeniden yapılandıralım. PDF sınıfıda Word sınıfıda aslında birer belge yani Document özelliğini taşıyor.
Şimdi Word ve PDF sınıflarını Document sınıfını extend edebilir.
Override anotasyonunu (annotation) görüyorsunuz. Anotasyonlar Java 1.5’ten sonra gelen bir özelliktir. Buradaki Override anotasyonu, Word ve PDF’te bulunan getPrintableText metodlarının ata sınıfın (Document) print metodunun değiştirildiği anlamına gelir.
Şimdi Printer sınıfını da yeniden düzenleyelim.
Şimdi daha iyi anlamanız için bir test sınıfı yazalım.
Eğer sonucu görmediyseniz lütfen sonucu tahmin etmeye çalışın.
Bu kodun ekran çıktısı aşağıdaki gibi olacaktır.
This is a document
This is a PDF document
This is a Word document
4. satırda yeni bir yazıcı sınıfı ürettik. 6. satırda bir döküman nesnesini yazdırdık. Beklediğimiz gibi Document sınıfında tanımladığımız metni yazdırdı. 8. satırda ise bir pdf belgesini yazdırmak istedik. Printer sınıfının parametre referans tipine baktığınızda Document olduğunu görüyorsunuz. PDF de bir document nesnesi olduğu için bu nesneyi bu metoda geçirebildik(passing). Bu polimorfizmin birinci durumu. Yani Document sınıfını extend eden herhangi bir nesneyi Document referansı ile kullabiliriz. Bunu şu şekilde de tanımlayabilirdik.
Document document = new PDF()
Yani Document dışında farklı sınıfların nesnelerini de Document referansı ile tanımlayabiliriz. Bunu polimorfizm sağlar. Polimorfizmin sağladı diğer bir güzellik ise ekranda gördüğünüz “This is a PDF document” yazısıdır. Document sınıfında tanımlanan varsayılan davranış yerine PDF sınıfında bu davranışı değiştirerek farklı metin yazmasına sebep olduk. Bu şekilde her nesnenin bir metod veya herhangi bir interface(java’daki interface’leri kastetmiyorum) için farklı davranış göstermesine polimorfizm diyoruz.
10. satırda aynı durum Word sınıfı için geçerli. Ayrıca Printer sınıfının tek bağımlılığı Document sınıfına oldu. Yani Printer ve Document sınıfını bir jar içerisinde müşteriye teslim edebiliriz. Bu da bize esnek bir yapı sağlar.
Şimdi gelelim müşterinin isteğine, müşteri bir Excel dosyası yazdırmak istemişti. Artık Printer sınıfına dokunmamıza bile gerek yok. Yeni bir Excel sınıfı ekleyelim.
super anahtar kelimesi
Java’da nesneyi üst sınıfın interface i ile kullanmak isterseniz. super
anahtar kelisini (keyword) kullanabilirsiniz.
Örneğimize bakarsak PDF sınıfı Document’in print metodunun üzerine kendi getPrintableText() metodunu deği davranışını
değiştirmiş oldu ve Document sınıfında tanımlanan print metodunun davranışını iptal etti.
Peki PDF sınıfı atasından (Document) aldığı getPrintableText() metodunu kullanmak isterse ne yapmalıyız?
İşte burda super anahtar kelimesini kullanabiliriz. PDF sınıfını aşağıdaki şekilde değiştirelim.
Bunun sonucunda getPrintableText() metodu “This is a document\nThis is a PDF document\n” değerlerini döndermiş olur.
Polimorfizm kavrami OOP’ye özgür bir özellik değildir. OOP ile uygulanabilir.
Bu yazımda polimorfizmi yüzeysel olarak anlatmaya çalıştım. Umarım faydalı olmuştur.
Bir sonraki yazıda görüşmek üzere…