10 Mart 2011 Perşembe

C# Abstract Nedir?

Sınıflara ve metotlara uygulanan bir anahtar sözcüktür. Abstract anahtar sözcüğü uygulanan tüm sınıflar ve metotlar, aynı zamanda virtual’dırlar. Ama virtual yazmamıza gerek yoktur. Şİmdi bu anahtar sözcüğün işlevini sınıflar ve metotlar için ayrı ayrı inceleyelim.

Abstract Class

Bir sınıfın abstarct olmasındaki amaç, bir takım sınıflara taban sınıf olmaktır. Bu nedenle Abstarct class’ların nesnesi üretilemez. Diğer önemli bir özelliği ise; abstract bir sınıfın içerisinde abstract metotlar tanımlanabilir.

Abstract Metot

Sadece abstract sınıfların içinde yazılabilen ve kalıtılan sınıflar tarafından override edilmek zorunda olan metotlardır. Private metotlara abstract anahtar sözcüğü uygulanamaz. Abstract metotları tanımlarken sadece imzalarını (geriye dönüş tipi ve parametreler) tanımlarız. Metodun gövdesi, kalıtılan sınıflarda oluşturulur. Diğer bir tanımlama şekli ise ; gövdesi olmayan ve ezilmek zorunda olan metotlardır.

Şimdi minik bir örnek verelim. Personel adında bir sınıf tasarlayalım.

abstract class Personel

    {

        public abstract void MaasBilgisi();

    }

Abstract bir class tanımladık. İçerisine de parametre almayan ve geriye değer dönmeyen bir metot tanımladık. Gördüğünüz gibi metodu tanımlarken süslü parantezler kullanmadık, yani metodun gövdesi yok. Bu sınıftan kalıtılan diğer sınıflar bu metodu override etmek zorundalar.

Şimdi de Personel sınıfından kalıtılan Stajyer adlı bir sınıf tasarlayalım.

class Stajyer : Personel

    {

 

    }

Programı bu haliyle derlemeye kalktığımızda bir hata ile karşılaşırız.

Error 1 : 'Abstract_II.Stajyer' does not implement inherited abstract member 'Abstract_II.Personel.MaasBilgisi()'

Personel sınıfındaki abstract üyeleri implement etmediğimiz için böyle bir hata aldık. Yapmamız gereken, MaasBilgisi metodunu override ederek gövde kazandırmaktır.

 

class Stajyer : Personel

    {

        public override void MaasBilgisi()

        {

            Console.WriteLine("Maaş = Asgari Ücret");

        }

    }

Simdi de Mudur sınıfı tasarlayaylım. Bu sınıf da personelden kalıtıldığından, MaasBilgisi aldı metodu override etmek zorundadır.

class Mudur : Personel

    {

        public override void MaasBilgisi()

        {

            Console.WriteLine("Maaş = 10000 TL");

        }

    }

Özetlemek gerekirse; kalıtılan sınıflarda ortak bir metot yazılacağı zaman, bu metodu taban sınıfa yazmak tasarım açısından daha doğru bir kodlama yapmamızı sağlar. Taban sınıfta yazılan bir metodun işleyişi;

  1. Kalıtılan tüm sınıflarda aynı ise abstract ya da virtual yazmaya gerek yoktur.
  2. Kalıtılan bazı sınıflarda farklılık gösteriyorsa virtual olarak tanımlanır ve ihtiyaç dahilinde override edilir.
  3. Kalıtılan tüm sınıflarda farklı ise, abstract olarak tanımlanır ve kalıtılan tüm sınıflarda metot override edilir.



34 yorum:

Adsız dedi ki...

çok iyi açıklama

Onur Salkaya dedi ki...

Teşekkürler

Adsız dedi ki...

Çok güzel bir anlatım teşekkürler

Adsız dedi ki...

Bencede anlatım çok başarılı.Teşekkürler

Adsız dedi ki...

adamın oracleısın

Adsız dedi ki...

yetersiz! gorsellik yok! akılda kalıcı değil! pff bunları biliyorum zaten detay lazım..!

Onur Salkaya dedi ki...

Madem biliyorsanız sayfayı kapatmanızı tavsiye ederim, iyi çalışmalar.

Adsız dedi ki...

Log sistemi ve oluşturulması hakkanda bilgi verir misiniz ?

Onur Salkaya dedi ki...

Bu çok genel bir konu ve fazlaca yöntem mevcut. Aklıma ilk geleni söyleyeyim, veri tabanında istediğimiz formata göre, (bu genellikle exception aldığımız assambly adı, namespace adı, sınıf adı, metot adı, satır numarası,hata mesajı, tarih vs) tablolar oluşturulabilir. Daha sonra da bir class library hazırlanarak bu tabloya insert işlemi gerçekleştiren metotlar yazılabilir. Ardından da bu tablo üzerinden ilgili kişilere mail gönderimi sağlanabilir.

Adsız dedi ki...

ÇOK BAŞARILI BİR ANLATIM GERÇEKTEN TEBRİK EDERİM.
BİZLERİ BİLGİLENDİRMEYE DEVAM EDERSENİZ ÇOK MUTLU OLURUZ.

Unknown dedi ki...

emeğinize sağlık çok teşekkürler.

Unknown dedi ki...

cok yardimci oldu tesekkur ederim

Adsız dedi ki...

harika anlatım teşekkürler, özellikle son 3 madde herşeyi özetliyor

Adsız dedi ki...

Verdiğiniz bu değerli bilgiden dolayı teşekkürler.

Sinan dedi ki...

Bir konudan bahsedilmemis fakat çok önemi olan bir ayrıntı. Abstract Class in deklerasyonu yapılmış degiskenlerini türetilmeş Class larda kullanmak çok güzel bir ayrıntı.

Unknown dedi ki...

Onu da iki-uc cumleyle kisaca siz anlatsaniz Sinan bey :) ?

Adsız dedi ki...

Kalıtılan bazı sınıflarda farklılık gösteriyorsa virtual olarak tanımlanır ve ihtiyaç dahilinde override edilir. cümlesi ile anlatmak istediğiniz nedir? abstract class da virtual olarak tanımlanış bir method , derived class'larda override edilmesi gerekmez mi? yani bir absract class içindeki bir method'un virtual method ya da abstract method olarak tanımlanması arasında ne fark vardır?

Onur Salkaya dedi ki...

Merhaba,

virtual metot override edilmek zorunda değildir. override edilmediği takdirde taban sınıftaki tanımlı olan işi yapar.

Ancak abstract method override edilmek zorundadır. Çünkü tanımlandığı taban sınıfta gövdesiz durumdadır (abstract metotların gövdeleri olmaz). Abstract metotlar aynı zamanda virtual'dırlar. Derlenen assembly'nin IL kodlarına bakıldığında bu görülebilir.

Adsız dedi ki...

Çok teşekkür ederim.

Adsız dedi ki...

teşekkürler.

Adsız dedi ki...

anlamadııım

Adsız dedi ki...

güzelde maaşbilgisi metodu ne zaman tetiklenecek

Onur Salkaya dedi ki...

Bir nesne örneklenip MaasBilgisi metodunu çağırdığı zaman tetiklenecek. Bir metot çağırılmadan, çalışacağını anlayamayacaktır takdir edersiniz ki...

Serdar dedi ki...

Abstract method override edilmek zorunda tamam anladım
abstract class larda abstract anahtar sözcüğü tanımlanmadığı durumlarda virtual olarak tanımlıdır dediniz..
peki bu durumda abstract class larında override edilme gibi düşünce geldi tabi bu classs larda tamam olmaz ama o zaman class lara abstract ifadesi koymanın anlamı nedir ?
virtual class içersinde abstract method tanımlansa olmuyormu ?

Serdar dedi ki...

birde bu iki satırda ne demek istediniz biraz açarmısınız ?

Kalıtılan tüm sınıflarda aynı ise abstract ya da virtual yazmaya gerek yoktur.

Kalıtılan tüm sınıflarda farklı ise, abstract olarak tanımlanır ve kalıtılan tüm sınıflarda metot override edilir.

Onur Salkaya dedi ki...

Merhaba,

"virtual" sözcüğü metotlar ya da property'ler için kullanılır. Anlamı ise "override edilebilir" , yani "ezilebilir" olarak düşünülmelidir.

"abstract" ise hem sınıflarda, hem de metot ve property'lerde kullanılabilir. "abstract" olan üye "override" edilmek zorundadır. "Ezilebildiğinden" dolayı da , "aynı zamanda virtual'dır" demek yanlış olmaz. Zaten IL kodlara bakıldığında abstract olan üyelerin virtual olduğunu görebilirsiniz.

"abstract" üyeler mutlaka abstract bir sınıf içerisinde olmak zorundadır.
Sınıflara "virtual" anahtar sözcüğünü kullanamayız.

İkinci sorunuza gelirsek,
Bir üyenin yapacağı işten bahsetmiştik, eğer bu iş , ilgili tipten kalıtılan tüm sınıflarda aynı işleyişe sahip olacaksa virtual ya da abstract olarak işaretlememize gerek yoktur. Eğer bazı alt sınıflarda farklılık ihtimali varsa virtual olarak tanımlarız, eğer tüm alt sınıflarda farklı ise abstract olarak tanımlarız.

Yani;
Taban sınıfta abstract olan bir üye , kalıtılan alt sınıflarda "ezilmek" zorunda olduğundan dolayı yukarıdaki cümleyi kullandık. Madem işleyiş tüm sınıflarda farklı olacak, o halde taban sınıftaki üyeyi "abstract" yaparak alt sınıflarda ezilmek zorunda bıraktık. Aksi halde kod derlenmeyecektir.

Serdar dedi ki...

şimdi anladım teşekkürler :)

Adsız dedi ki...

hocam

benim örnek 5 tane sııfım var bazıları property field bazıları methodlardan oluşuyor
ve ben bunları atıyorum 20 farklı tane class içersinde kullanıyorum
her class içine gelip bu 5 tane sınıfı new ile instance yapıyorum sonra kullanıyorum
yani tam bir eziyet ve spagetti kodlama
istediğim basit ortak bir base constractor sınıfı olacak tüm bu 5 sınıfım bunun içinde olacak yani new ile oluşturulacak..
ben nerde bu sınıfları kullanacaksam
ilgili sınıftan onu cağırcam yada inherit edeceğim
bilmiyorum yanlış belki ama kısaca sürekli yazmak istemiyorum
acaba depencty injection yada abstraction ile olurmu ? olursa rica etsem örneklermisiniz teşekkürler

serdar dedi ki...

yada daha teknik bir kodlama olsun ben ortak kullanacağım sınıflar örnek tek base bir sınıf içinde olacak
diyelim içinde

MakaleSınıfı
DersSınıfı
EditorSınıfı

olacak ben bu sınıflardan hangisini kullanacaksam ilgili sınıfta bunları inherit etmek istemiyorum çünkü başka bir inherit ilerde olabilir interfacede kullanmak istemiyorum
basitce kullanmak istediğim sınıf içinde bu sınıflar hangi sınıf içindeyse kullanacağım sınıfın adını göndermek ve onların içindeki methodları kullanmak
örnek

public class yayin
{

public yayin()
{
var value = ortakSinif(new makale()); yani atıyorum tabi dogru yazmadım.. makale sınıfını kullanacaksam onunn adını göndercem Editor ise onun adını göndercem value. dediğim anda o sınıfın içindeki methodları görebileceğim ?
}
}

teşekkürler

serdar dedi ki...

pardon adsiz olan kişide benim .. yanlışlıkla adımı yazmamısım

Onur Salkaya dedi ki...

En basit ve ilken yöntem ile "yayin" adlı constructor'a dışarıdan parametre göndererek bu işi yapabilirsiniz. Sonrasında gelen parametre tipine göre "if ( parametre is Makale)" şeklinde, ya da switch case'ler kullanarak ilgili nesneleri örnekleyebilirsiniz.

Ancak bu iyi bir çözüm değil. Daha da iyileştirebilmek için dışarıdan parametre gelecek ortak tiplere göre (elinizde 5 sınıf olduğunu varsayıyorum), bu 5 sınıfın da taban sınıfı olan (ya da bir interface) nesneyi baz alarak ortak metotlar yazabilirsiniz.

public yayin(IOrtakSinif ortakSinif)
{
ortakSinif.OrtakMetot();
}

Tüm bunların dışında sizin de bahsettiğiniz gibi Dependency Injection yöntemini de kullanabilirsiniz. Ancak elinizde 5 tane nesne var ise ve sürekli değişik tipler kullanarak nesne üretecekseniz size bu esnekliği sağlamayabilir. Yine de .net'in içerisindeki "Unity IOC Container" ya da "Castle Windsor" gibi kütüphaneleri de kullanabilirsiniz

Adsız dedi ki...

Çok güzel bu kadar net ve kısa olur en sonunda anladım..

Unknown dedi ki...

:) bunca yıl geçmiş hala tazeliğini koruyor.Mis gibi olmuş.Öz ve .net . teşekkürler.

Semih Çelikol dedi ki...

Güzel anlatım olmuş, teşekkürler.

Yorum Gönder