Tamamen kalıtım amaçlı kullanacağımız temel sınıfları oluştururken Abstract anahtar sözcüğünü kullanırız. Abstract bir sınıf oluşturabilmek için erişim belirtecinden sonra “abstract” anahtar sözcüğünü yazmamız gerekmektedir. Abstract sınıflar içerisinde hem metot tanımlayabilir hem de arayüzler de olduğu gibi metot bildirimi yapabiliriz.
public abstract class TemelSinif { public void Metot_1() { Console.WriteLine("Abstract sınıf içerisinde tanımlanmış metot."); } public abstract void Metot_2(); }
TemelSinif, abstract bir sınıf olduğu için sadece kalıtım amaçlı kullanılabilir. Metot_1(), TemelSinif‘dan türetilen sınıflara doğrudan aktarılacaktır. Bildirimi yapılmış olan Metot_2()‘nin ise türetilmiş sınıflar içerisinde tanımlanması (metot gövdesinin yazılması) gerekmektedir.
Abstract sınıflarda metot bildirimi yapabilmek için erişim belirtecinden sonra “abstract” anahtar sözcüğünü yazmamız gerekmektedir.
public class TuretilmisSinif : TemelSinif { public override void Metot_2() { Console.WriteLine("Türetilmiş sınıf içerisinde tanımlanmış metot."); } }
TuretilmisSınıf, TemelSinif‘dan türetildiği için TuretilmisSınıf içerisinde Metot_2()‘nin tanımlamasını yapmamız gerekmektedir. Bu örnekten de anlaşılacağı üzere abstract sınıfları arayüzler (interface) gibi kullanabiliriz.
Abstract sınıf içerisinde bildirimi yapılmış olan metotları (Bkz: Metot_2()) türetilmiş sınıflar içerisinde tanımlayabilmemiz için override anahtar sözcüğünü kullanmamız gerekmektedir.
class Program { private static void Main(string[] args) { TuretilmisSinif turetilmisSinif = new TuretilmisSinif(); turetilmisSinif.Metot_1(); turetilmisSinif.Metot_2(); } }
Ekran çıktısı:
Abstract sınıf içerisinde tanımlanmış metot. Türetilmiş sınıf içerisinde tanımlanmış metot. Press any key to continue . . .
Abstract Sınıfların Normal Sınıflardan Farkı Nedir?
Fark 1: Normal sınıflar içerisinde metot bildirimi yapılamazken, Abstract sınıflar içerisinde tıpkı arayüzler de olduğu gibi metot bildirimi yapılabilir. Bildirimi yapılan metotlar, Abstract sınıftan türeyen sınıflar içerisinde tanımlanmak zorundadır.
Fark 2: Normal sınıflardan “new()” anahtar sözcüğü ile nesneler oluşturulabilir ancak Abstract sınıflar tamamen kalıtım amaçlı geliştirildiğinden Abstract sınıflardan nesne oluşturulamaz.
TuretilmisSinif turetilmisSinif = new TuretilmisSinif(); (Doğru) TemelSinif temelSinif = new TemelSinif(); (Yanlış)
Abstract Sınıfların Arayüzlerden Farkı Nedir?
Fark 1: Arayüzlerde sadece metot bildirimi yapılabilirken Abstract sınıflarda hem metot bildirimi yapılabilir hem de metot tanımlanabilir.
Fark 2: Bir sınıfa sadece bir tane Abstract sınıf inherit edilebilir ancak aynı sınıfa birden fazla arayüz implement edilebilir.
public abstract class AbstractSinif_1 { public abstract void Metot_1(); } public abstract class AbstractSinif_2 { public abstract void Metot_2(); } public class TuretilmisSinif : AbstractSinif_1 { public override void Metot_1() { Console.WriteLine("Metot_1() tanımlandı."); } }
TuretilmisSinif‘a Abstract sınıflardan sadece bir tanesini inherit edebiliriz. Yani TuretilmisSinif‘a hem AbstractSinif_1‘i hem de AbstractSinif_2‘yi inherit edemeyiz.
public class TuretilmisSinif : AbstractSinif_1 , AbstractSinif_2 {} // YANLIŞ!
Ancak bir Abstract sınıfa, başka bir Abstract sınıfı inherit ederek bu kısıtı kaldırmak mümkün.
public abstract class AbstractSinif_1 : AbstractSinif_2 { public abstract void Metot_1(); } public abstract class AbstractSinif_2 { public abstract void Metot_2(); } public class TuretilmisSinif : AbstractSinif_1 { public override void Metot_1() { Console.WriteLine("Metot_1() tanımlandı."); } public override void Metot_2() { Console.WriteLine("Metot_2() tanımlandı."); } }
AbstractSinif_1‘e AbstractSinif_2 inherit edildiği için, AbstractSinif_1‘den türetilen bir sınıf hem AbstractSinif_1 içerisinde bildirimi yapılmış olan metodu (Metot_1()) hem de AbstractSinif_2 içerisinde bildirimi yapılmış olan metodu (Metot_2()) içermek zorundadır.
Abstract Sınıflara Hangi Durumlar da İhtiyaç Duyarız
Yılın her bir ayı için bir sınıf oluşturmamız gerektiğini düşünelim ve bu sınıflar içerisinde ilgili ayın kaç günden oluştuğu, yılın kaçıncı ayı olduğu ve her bir gününün kaç saatten oluştuğu bilgilerini döndürecek metotların olmasını istediğimizi varsayalım.
public interface Ay { int GunlerKacSaattir(); int KacGundenOlusur(); int YilinKacinciAyidir(); }
İlk başta aklımıza bir arayüz kullanmak gelebilir. Ay isminde bir arayüz tanımlayıp, içerisinde ihtiyacımız olan metotların bildirimini yaptıktan sonra bu arayüzü aylarımızı temsil eden sınıflara implement ederek bir çözüm geliştirebiliriz.
public class Ocak : Ay { public int GunlerKacSaattir() { return 24; } public int KacGundenOlusur() { return 31; } public int YilinKacinciAyidir() { return 1; } } public class Subat : Ay { public int GunlerKacSaattir() { return 24; } public int KacGundenOlusur() { return 28; } public int YilinKacinciAyidir() { return 2; } } public class Aralik : Ay { public int GunlerKacSaattir() { return 24; } public int KacGundenOlusur() { return 31; } public int YilinKacinciAyidir() { return 12; } }
Ancak ayları temsil eden sınıfları dikkatlice inceleyecek olursak, GunlerKacSaattir() metodunun hepsinde aynı sonucu döndürecek şekilde tanımlandığını görebiliriz. Her bir ay için aynı metodu tekrar tekrar tanımlayıp kod tekrarı yapmak yerine, bir defaya mahsus tanımlamak çok daha verimli olacaktır. Arayüzler içerisinde metot tanımı yapılamayacağından, bu örnekte arayüz yerine abstract sınıf kullanacağız.
public abstract class Ay { public int GunlerKacSaattir() { return 24; } public virtual int KacGundenOlusur() { return 31; } public abstract int YilinKacinciAyidir(); }
İçerisinde hem metot tanımı hem de metot bildirimi yapabileceğimiz bir yapıya ihtiyacımız olduğundan Ay isminden bir abstract sınıf oluşturduk. GunlerKacSaattir() metodu tüm aylar için aynı sonucu döndüreceğinden, bu metodu direkt abstract sınıf içerisinde tanımladık. Böylece 12 ay için aynı metodu 12 defa yazmak yerine, bir defa yazmış olduk.
Eğer bir metot tüm türetilmiş sınıflarda aynı şekilde tanımlanıyorsa o metodu abstract sınıf içerisinde standart bir metot tanımlar gibi tanımlarız.
KacGundenOlusur() metodunu abstract sınıf içerisinde tanımlamak yerine sadece bildirimini yapıp, Ayları temsil eden sınıflarımız içerinde tanımlayabilirdik. Ancak bu metot Ocak, Mart, Mayıs, Temmuz, Ağustos, Ekim ve Aralık ayları için aynı sonucu (31) döndürmesi gerektiğinden, en azından bu aylar için tekrardan KacGundenOlusur() metodunun tanımını yapmamak adına varsayılan olarak geriye 31 döndüren ancak istenilen sınıf içerisinde override edilerek yeniden tanımlanabilecek şekilde kullanılabilmesi için virtual olarak tanımladık (Bkz: C# – Virtual Metotlar).
Eğer bir metot bir çok türetilmiş sınıfta aynı şekilde tanımlanıyor iken sadece bir kaçında değişik şekilde tanımlanıyorsa o metot abstract sınıf içerisinde virtual olarak tanımlanır.
YilinKacinciAyidir() metodu her bir ay için farklı bir değer döndüreceğinden, bu metodun sadece bildirimi yapıyoruz.
Eğer bir metot tüm türetilmiş sınıflarda farklı şekilde tanımlanıyorsa o metodun abstract sınıf içerisinde sadece bildirimi yapılır.
public class Ocak : Ay { public override int YilinKacinciAyidir() { return 1; } } public class Subat : Ay { public override int KacGundenOlusur() { return 28; } public override int YilinKacinciAyidir() { return 2; } } public class Aralik : Ay { public override int YilinKacinciAyidir() { return 12; } }
Serdar YILMAZ
Teşekkürler.
teşekkürler virtual ne demek, override ne demek, abstract ne demek güzel anlaşıldı
Gayet açıklayıcı
Son derece açıklayıcı bir dil. Emeğinize sağlık.
Bloğunuz ve anlatım tarzınızı çok beğeniyorum. Emeğinize sağlık
Teşekkürler.
mükemmel bir yazı çok deüerlisiniz hocam emeklerinize sağlık. verdiğiniz bilgiler için çok teşekkürler.
Yazınızı çok beğendim ellerinize sağlık. Virtual metotlar, kalıtım ve interface konularıyla beraber çok güzel bir şekilde özümsedim. Bu konuyu anlamak için bahsettiğim konuları da bilmek gerekiyor. Sanırım o konular da bu sitede var.
Ellerinize sağlık güzel, anlaşılır anlatım.
Çok başarılı bir yazı olmuş tebrikler. Yeni başlayan bir insan için gerçekten faydalı bir içerik şeklinde oluşturulmuş.
Ellerinize saglik cok guzel anlatmissiniz
Mükemmel Çok Teşekkürler
çok güzel bir makale, ellerine sağlık.
çok temiz anlaşılır güzel bir makale olmuş teşekkürler
Çok güzel ve ayrıntılı bir anlatım olmuş emeğiniz için teşekkür ederim
Teşekkürler abstract ve override kavramlarını çok iyi anladım sayenizde.