Abstract Class Nedir? Neden Kullanıyoruz?
Nesne tabanlı programlamanın önemli kavramlarından ve davranışlarından biri inheritance (kalıtım)’dır. Kalıtım sayesinde sınıflar arasında hiyerarşik ilişkiler oluşturabilir ve nesneler içerisindeki elemanları miras yoluyla birbirlerine aktarabiliriz. Böylece ortak işlevselliklere sahip olan sınıfları kalıtımsal davranışla şekillendirerek tekrar kod yazımını azaltır, okunabilirliği ve yeniden kullanılabilirliği artırabiliriz.
Abstract Class, bu niyetle kullandığımız kalıtımsal davranışı daha farklı manevralarla kullanabilmek için düşünülmüş ve geliştirilmiş olan bir nesnel yapıdır. Abstract Class, özünde kalıtımsal davranış göstererek bir sınıf üzerinde implementasyonlar yapmamızı sağlayan özel bir yapılanmadır.
Burada implementasyondan kastedilenin ne olduğunu yazımızın ilerleyen kısımlarında anlatacağız. Şimdilik odaklanacağımız nokta Abstract Class’ın varlık sebebidir. Abstract Class bize yarı somut bir sınıf sunar. Yarı somut sınıftan kasıt, içerisinde normal member’lar barındırabileceği gibi, kendisini uygulayan sınıflara zorunlu olarak uygulatılacak member’ların imzalarını da barındırabilen bir yapılanmadır.
Burda Shape adında bir abstract class tanımlanıyor ve içerisinde CalculateArea adında abstract bir method ve DisplayInfo adında concrete bir method bulunuyor. Circle sınıfı Shape sınıfını miras alarak CalculateArea methodunu override edip dairenin alanını hesaplıyor. Benzer şekilde, Rectangle sınıfı da Shape sınıfını miras alarak CalculateArea methodunu override edip dikdörtgenin alanını hesaplıyor. Main metodunda Circle ve Rectangle sınıflarından nesneler oluşturuluyor, nesnelerin CalculateArea methodları çağrılarak alanları hesaplanıyor ve DisplayInfo methodu ile nesnelerin türü ekrana yazdırılıyor. abstract classa örnek veriyorum konuya giriş yaparker. İlerleyen bölümlerde detaylara gireceğim.
// Abstract Class tanımlama
public abstract class Shape
{
// Abstract method (implementation yok)
public abstract double CalculateArea();
// Concrete method (implementation var)
public void DisplayInfo()
{
Console.WriteLine("This is a shape.");
}
}
// Circle sınıfı Shape'i miras alıyor
public class Circle : Shape
{
public double Radius { get; set; }
// Abstract metodu override ediyor
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
// Rectangle sınıfı Shape'i miras alıyor
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
// Abstract metodu override ediyor
public override double CalculateArea()
{
return Width * Height;
}
}
public class Program
{
public static void Main(string[] args)
{
Shape circle = new Circle { Radius = 5 };
Shape rectangle = new Rectangle { Width = 4, Height = 7 };
Console.WriteLine("Circle Area: " + circle.CalculateArea());
Console.WriteLine("Rectangle Area: " + rectangle.CalculateArea());
circle.DisplayInfo(); // Output: This is a shape.
rectangle.DisplayInfo(); // Output: This is a shape.
}
}
Yazılım Süreçlerinde Abstract Class Kullanımı
Yazılım süreçlerinde Abstract Class’ları kullanma nedeni belirli bir ihtiyaca dayanmaz; tercihen kullanılan yapılardır. Genellikle Abstract Class’lara doğrudan gereklilik olduğu bir durum pek olmaz. Ancak belirli durumlarda iradeli bir şekilde Abstract Class’lar ile davranışı sergilemeyi tercih edebilir ve varsa sorunlarınızı daha basit hale getirebilirsiniz.
Bir Abstract Class ile kalıtımsal olarak aktarmak istediğiniz davranışlarla birlikte zorunlu olarak uygulatmak istediğiniz davranışları tasarlayabilirsiniz. Bu tasarımı istediğiniz sınıflara uygulatarak hem kalıtımsal aktarımda bulunabilir hem de o sınıflar içerisinde zorunlu olarak ilgili davranışları tanımlatabilirsiniz.
Abstract Class’ın yapısal özellikleri nelerdir?
Abstract Class’ın Temel Özellikleri:
Abstract Class her ne kadar abstract olsa da özünde bir class’tır. Yani referans türünde bir yapılanmadır. Dolayısıyla Abstract Class türünden belleğin stack bölgesinde bir referans noktası edinilebilir ve bu referansla heap’teki uygun nesneler işaretlenebilir.
// Abstract Class tanımlama
public abstract class Shape
{
// Abstract method (implementation yok)
public abstract double CalculateArea();
// Concrete method (implementation var)
public void DisplayInfo()
{
Console.WriteLine("This is a shape.");
}
}
Abstract Class ile Nesne Arasındaki İlişki:
Abstract Class’lar soyut yapılanmalar oldukları için yapısal olarak iradeli bir şekilde (new operatörü ile) nesne üretilemez.
Shape shape = new Shape(); // Bu satır derleme hatası verir!
Abstract Class’tan doğrudan nesne oluşturulamaz, ancak bu sınıfı implement eden (uygulayan) sınıflar üzerinden nesne oluşturulabilir.
// Circle sınıfı Shape'i miras alıyor
public class Circle : Shape
{
public double Radius { get; set; }
// Abstract metodu override ediyor
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
// Rectangle sınıfı Shape'i miras alıyor
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
// Abstract metodu override ediyor
public override double CalculateArea()
{
return Width * Height;
}
}
public class Program
{
public static void Main(string[] args)
{
Shape circle = new Circle { Radius = 5 };
Shape rectangle = new Rectangle { Width = 4, Height = 7 };
Console.WriteLine("Circle Area: " + circle.CalculateArea());
Console.WriteLine("Rectangle Area: " + rectangle.CalculateArea());
}
}
Abstract Class Tanımlama ve İnşa Etme Kuralları:
Bir Abstract Class tanımlamak için abstract class
anahtar kelimesi kullanılır.
public abstract class Animal
{
public abstract void MakeSound();
}
Bir Abstract Class içerisinde member’lar bilinen kurallara göre eklenebilir: normal metotlar ve property’ler eklenebilir.
public abstract class Animal
{
public string Name { get; set; }
public abstract void MakeSound();
public void Sleep()
{
Console.WriteLine("Sleeping...");
}
}
Bu Abstract Class’ı implement edecek olan sınıflarda zorunlu tanımlanmasını isteyebileceğimiz member imzaları eklenebilir. Bu imzalar, ilgili alt sınıflara bırakılacak şekilde abstract anahtar kelimesi ile işaretlenmelidir. Tabi abstract anahtar kelimesi ile işaretlenmiş olan member’lar, kendilerini uygulayan sınıflar tarafından erişileceği için zorunlu olarak public olmalıdır.
public abstract class Animal
{
public abstract void MakeSound();
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
Bir Abstract Class’ı uygulayan sınıf içerisinde normal member’lar direkt miras yoluyla aktarılırken, abstract ile işaretlenmiş olan member’lar ise ilgili sınıf içerisinde override edilmek zorundadır.
public abstract class Animal
{
public abstract void MakeSound();
public void Sleep()
{
Console.WriteLine("Sleeping...");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow!");
}
}
public class Program
{
public static void Main(string[] args)
{
Cat cat = new Cat();
cat.MakeSound(); // Output: Meow!
cat.Sleep(); // Output: Sleeping...
}
}
Virtual ile Abstract Arasındaki Fark:
Eğer bir member virtual
ile işaretlenmişse, alt sınıfta değiştirmek zorunda değilsiniz; olduğu gibi kullanılabilir. Ancak abstract
ile işaretlenmişse, alt sınıfta içeriği tanımlamak zorundasınız.
public class BaseClass
{
public virtual void ShowMessage()
{
Console.WriteLine("Message from BaseClass.");
}
}
public class DerivedClass : BaseClass
{
// Virtual metodu override etmek zorunda değilsiniz
}
public class AnotherDerivedClass : BaseClass
{
// Virtual metodu override ediyor
public override void ShowMessage()
{
Console.WriteLine("Message from AnotherDerivedClass.");
}
}
public class Program
{
public static void Main(string[] args)
{
BaseClass baseObj = new BaseClass();
BaseClass derivedObj = new DerivedClass();
BaseClass anotherDerivedObj = new AnotherDerivedClass();
baseObj.ShowMessage(); // Output: Message from BaseClass.
derivedObj.ShowMessage(); // Output: Message from BaseClass.
anotherDerivedObj.ShowMessage(); // Output: Message from AnotherDerivedClass.
}
}
Abstract Class’ı Uygulamaktan Kastettiğimiz Nedir?
Abstract Class’ın söz konusu olduğu durumlarda implementasyon yani uygulama fiiliyatı mevzubahistir. Bu durum, sonraki derste göreceğimiz interface’ler için de geçerlidir. Implementasyon, Abstract Class’ın bir sınıfa katma vermesidir. Yani bir başka deyişle kalıtımsal bir ilişkide eğer base class bir Abstract Class ise biz bu durumu implementasyon olarak nitelendiririz.
Abstract Class’ın Abstract Class’tan Türemesi
Abstract Class başka bir Abstract Class’tan miras alabilir.
// Temel Soyut Sınıf
public abstract class Hayvan
{
// Soyut metod (uygulama yok)
public abstract void SesCikar();
// Somut metod (uygulama var)
public void Uyu()
{
Console.WriteLine("Uyuyor...");
}
}
// Türetilmiş Soyut Sınıf
public abstract class Kus : Hayvan
{
// Soyut metod (uygulama yok)
public abstract void Uc();
}
// Somut Sınıf
public class Serce : Kus
{
// Soyut metodları geçersiz kılıyor (override)
public override void SesCikar()
{
Console.WriteLine("Cik Cik");
}
public override void Uc()
{
Console.WriteLine("Serçe uçuyor.");
}
}
public class Program
{
public static void Main(string[] args)
{
Serce serce = new Serce();
serce.SesCikar(); // Çıktı: Cik Cik
serce.Uc(); // Çıktı: Serçe uçuyor.
serce.Uyu(); // Çıktı: Uyuyor...
}
}
Özetle
bir sınıfın uyması gereken temel yapıyı tanımlamak için Abstract Class yapısını kullanabilir ve gerekli modellemeyi gerçekleştirebilirsiniz. Abstract Class’lar bir çeşit abstraction yapılanmasıdır. Davranışların var olduğunu garanti eder, ancak davranışın implementasyonunu interface’ler gibi zorunlu kılmaz. Abstract Class’lar, interface’ler ile concrete/normal class’lar arasında bir yapıdır. Abstract Class’lar, birçok senaryo için geçerli olabilecek genel davranışlar sağlayabileceği gibi, bazı senaryolar için ise özel davranışlar da barındırabilir. Abstract Class, doğrudan inheritance ve polymorphism ile bağlantılı bir kavramdır. Özellikle inheritance olmaksızın Abstract Class kullanılmaz. Keza inheritance amaçlı kullanılan yapı Abstract Class ise o zaman oradaki ifadeye implementasyon denir. Abstract Class’lar (interface’ler de aynı şekilde) loose coupling’i destekler.
Yorum Yap