Nesne tabanlı programlama (object oriented programming) yaparken, hazırladığımız classlar için base classlar hazarlarız. Bunu yaparken normal class, abstract class, interface kullanırız. Peki hangisi ne işe yarar, hangisini hangi durumlarda kullanmalı?
Öncelikle abstract class ve interface için şunu söyleyebiliriz; direk olarak değişken yaratamayız bunlardan. Tamamen tanım amaçlı yazıldıkları için, normal class gibi kullanılamazlar. Haliyle eğer değişkene atayıp (instance) kullanmak istiyorsak taban class'ımızı mutlaka bu seçenekler arasından normal class'ı seçmeliyiz.
Abstract class ile interface karşılaştırması yapmak istersen öncelikle söyleyebileceğimiz bazı farklar var aralarında. Abstract classlar; abstract metodlar (methods), abstract özellikler (properties) gibi diğer üyeleri de barındırabilirler. (Tıpkı normal classlar gibi). Interfaceler ise; Zaten abstract ya da public kelimelerini kullanmamıza gerek kalmadan, içinde tanımladığımız bütün metodları ve özellikleri public ve abstract olarak taşırlar. Yani başka bir şansımız zaten yoktur. Örnek olarak aşağıdaki koda bakalım.
//Abstarct Class
public abstract class Vehicles {
private int noOfWheel;
private string color;
public abstract string Engine {
get;
set;
}
public abstract void Accelerator();
}
//Interface
public interface Vehicles {
string Engine {
get;
set;
}
void Accelerator();
}
Gördüğümüz gibi abstract classlarda özellikleri ve diğer üyeleri private olarak da tanımlayabildiğimiz gibi aynı zaman da metodları da implemente de edebiliyoruz. Esasen abstract class için gerçek dünyada kullandığmız varlıklar için daha bir tanımlayıcı bakışa sahip olduklarını ancak interfacelerin çok daha tanımlayıcı amaçla kullanıldıklarını söyleyebiliriz. Varlıklar hakkında konuşabileceğimiz iki temel konu vardır. Birincisi maksat, ikincisi ise uygulamadır. Maksat derken buradaki kasıt; durum ve davranıştır, nasıl göründüğü ya da nasıl çalıştığı değil (belki birazcık bilinebilir ama tam denilemez). Uygulama derken de; uygulanırken ki durumu (yani gerçek durumu) ve davranışıdır.
Biraz teoriden sıyrılıp, bir örnek üzerinden bakalım konuya.
Bir CMS düşünelim (Content Management System - İçerik Yönetim Sistemi). İçerik; makale, blog ve eleştiriler olsun. Demek ki bu üç farklı şeyin bir ortak noktası var temel olarak o da üçünün de içerik olması. Icerik bizim tabanımız olacak demek ki. Peki Icerik, normal class mı, abstract class mı yoksa interface mi olmalı? Düşündüğümüz iş mantığı (business logic) çerçevesinden bakınca eğer Icerik uygulamanın temel varlığı olmayacak ve kullanılacak bir nesne olmayacaksa - ki bu örnek bu cümleye uyuyor çünkü bu uygulama da temel varlıklar makale, blog ve eleştirilerdir - ; o zaman normal class yapmamalıdır. Geriye abstract class ve interface kalıyor.
Bu uygulama da her içeriğin yayınlanabilmesi gerekiyor. Haliyle, Icerik tanımının mutlaka içinde bir "yayınla" komutuna ihtiyacı vardır, bu durumda Icerik tanımını mutlaka abstract class olarak yapmak gerekir. Eğer iş mantığımda her içeriğin varsayılan ortak komutu olmasaydı (yayınla komutu mesela), o zaman abstract class'a gerek kalmazdı ve interface de kullanabilrdim. Bunlar normal class, abstract class ve interface arasında seçim yapılacağı zaman en temel farklar oluyorlar. Ama şu gerçeği unutmamak lazım ki, üzerinde konuştuğumuz şey yazılım ve değişmeyen tekşey zaten değişimin ta kendisi. Mesela eğer Icerik tanımını interface olarak yapsaydım, değişiklik yapmam zorlaşırdı. Icerik de yaptığım her değişikliği aynen, Icerikten türettiğim bütün nesnelere yansıtmak zorunda kalacaktım. Bunun üstesinden Icerik'i abstract class olarak tanımlayarak gelebiliyorum ancak unutmamak gereken bir tek durum dışında; çoklu miras (multiple inheritance). Interface ve abstract classları ayıran bir değer fark da CAN-DO (yapabilir) ve IS-A (böyledir) bağlantılarıdır. Az evvel bahsettiğim gibi interface'i çoklu miras için kullanabiliyoruz. Misal olarak bir de kopyalama davranışı veren "ICopy" adında bir interface'imiz olsun ki bu da genelleştirme ve uzmanlaştırma, özelleştirme durumu için bir IS-A bağlantısıdır. Yani türemiş bütün nesneler kendi kopyalama davranışlarına sahip olmak zorunda kalırlar. Eğer makale tanımı; abstract class olan Icerik'ten ve interface olan ICopy'den türerse bu da makale nesnesinin kopyalama yapabildiğini gösterir ki bu da CAN-DO'dur.
Biraz teorik olarak biraz pratik desteğiyle konuyu derinlemesine anlatmaya çalıştım. Konuyu toparlamak gerekirse; abstract class, temel kimliği tanımlar. Bence abstract class günü kurtarır ve hızlıca devam edebilmeyi sağlar yani interface bence daha dikkatli kullanım ve yavaşlık getirir, gerektirir. Tabi daha önce de belirttiğim gibi interface'in en büyük avantajı ve abstract class'tan farkı çoklu miras (multiple inheritance)'dır.
İyi çalışmalar dilerim.