You are on page 1of 7

BİR SINIFIN ANATOMİSİ

Sınıf, belli özelliklere göre nesneleri gruplamaktır. Örneğin; çam, meşe vs gibi nesneler ağaç
olarak sınıflandırılabilir. Aynı şekilde ağaç, çiçek, ot gibi sınıflar da gruplanarak bir üst sınıf
olan bitkiler sınıfını oluşturur. Bitkiler, insanlar, hayvanlar da gruplanarak canlılar sınıfını
oluşturmaktadır. Bu ağaç yapısını kökten başlayarak analiz edecek olursak; canlılar sınıfı
temel sınıftır. Bitkiler, insanlar, hayvanlar bu temel sınıftan türemiş sınıflardır. Ağaç, çiçek, ot
ise bitkiler sınıfından türemiş sınıflardır. En sonda ise çam, meşe vs. ağaç sınıfından türemiş
nesnelerdir. Her sınıfın belli başlı özellikleri ve fonksiyonları vardır. Örneğin; ağaç sınıfının
türü, boyu vs. gibi özellikleri ve fotosentez yapma gibi fonksiyonları vardır. Ağaç sınıfından
türeyen her nesne bu temel özellikleri ve fonksiyonları miras almaktadır. Nesne yönelimli
programlamadaki sınıf kavramının bu benzetmeden farkı yoktur. Bu makalede sınıf kavramı
üzerinde duracağız. Sınıflar yazacak, türetme yapacak ve sınıflarda neler bulunur, bunları
inceleyeceğiz.

Örnek olarak "Canlilar" sınıfını yazacak, sonra "Canlilar" sınıfından "Insan" sınıfını türetecek
ve nihayetinde "Insan" sınıfından "Mustafa" nesnesini oluşturacağız. Bu süreç içerisinde
sınıflar içerisinde kullanılan alanlardan, özelliklerden, fonksiyonlardan, metodlardan,
yapıcılardan, temsilcilerden yeri geldikçe bahsedeceğiz. Yapıcı metodlar ile başlayalım.

Bir sınıfın yeni bir kopyası oluşturulurken, sınıfın yapıcı metodu çalışmaktadır. Yapıcı metod
sınıf ile aynı ada sahiptir. Varsayılan yapıcı metod parametre almaz. Ancak çeşitli
parametreleri vererek birden fazla yapıcı metod tanımlayabiliriz. Buna aşırı yükleme
denilmektedir. Yapıcı metod tanımlarken dikkat edilmesi gereken nokta metodun sınıf ile
aynı ada sahip olması ve birden fazla yapıcı metod tanımlanmış ise metodların
parametre sayılarının veya parametre türlerinin birbirinden farklı olmasıdır. Aşağıda
"Canlilar" sınıfımız ve yapılandırıcıları verilmiştir.

class Canlilar
{
private static string tur;
private static int yas;
public Canlilar()
{
}
public Canlilar(string turu)
{
tur = turu;
}
public Canlilar(string turu, int yasi)
{
tur = turu;
yas = yasi;
}
}

İlk yapılandırıcımız varsayılan yapılandırıcıdır. Nesne herhangi bir parametre almadan


oluşturulur. İkinci yapılandırıcımız canlının tür bilgisini alarak "Canlilar" sınıfının kopyasını
oluşturmaktadır. Üçüncü metodumuz ise tür ve yaş bilgilerini alarak sınıfımızın kopyasını
oluşturmaktadır. "Canlilar" sınıfını oluştururken girdiğimiz bu parametreler sınıf içerisinde
tanımlanan "tur" ve "yas" değişkenlerine aktarılarak sınıf içerisindeki işlemlerde
kullanılmaktadır. Değişkenleri ve yapıcıları tanımlarken private ve public belirteçlerini
kullandık. Private belirteci tanımlanan değişkenin, metodun vs. sadece o sınıf içerisinden
erişilebileceğini belirtmektedir. Aksi belirtilmediği sürece bütün değişkenler, metodlar private
tanımlanmıştır. Public belirteci ile tanımlanan değişkenlere, metodlara vs. bütün sınıflardan
erişim sağlanmaktadır. Bu iki belirtecin dışında hem sınıf içerisinden hem de referans
gösterildiği diğer sınıflardan erişim sağlayan protected, içinde bulunduğu sınıfa ait assembyl
tarafından erişim sağlayan internal belirteçleri vardır.

Her canlı sınıfının bir türü vardır. Tür, canlılar sınıfının sahip olduğu bir özelliktir. Şimdi
Canlılar sınıfımıza tür özelliğini ekleyelim.

public string Tur


{
get { return tur; }
set { tur = value; }
}

"Tur" özelliği hem dışarıdan değer alan hemde içerdiği değeri çağrıldığı yere aktaran bir
yapıdadır. Yani hem okunabilir hem yazılabilir. Set bloğunda aldığı değeri "tur" değişkenine
aktarır. Get bloğunda ise "tur" değişkeninin değerini çağrıldığı yere return eder. Özellikler
ReadOnly'de olabilir. Bunun için sadece get bloğu yazılır.

public string SinifBilgisi


{
get { return "Canlilar sınıfı."; }
}

"SinifBilgisi" adlı bu özellik kullanıldığında "Canlılar sınıfı." stringini return eder.


"SinifBilgisi" özelliğine değer atadığımızda bu özelliğin ReadOnly olduğunu belirten bir hata
ile karşılaşırız. Özelliklerin yanında sınıflarda bazı işlevleri yerine getiren fonksiyonlar
olabilir. Örnek olarak "Canlilar" sınıfımızda dışarıdan canlının doğum tarihini alıp geriye
yaşını return eden bir fonksiyon olsun.

public int YasHesapla(DateTime dogumTar)


{
int dogumTarihi = dogumTar.Year;
yas = Convert.ToInt32(DateTime.Now.Year) - dogumTarihi;
return yas;
}

Bir sınıf içerisinde yazdığımız bir fonksiyonun içeriğine, bu sınıftan türettiğimiz bir sınıfta
eklemeler yapabilir veya içeriğini tamamen değiştirebiliriz. Bunun için sonradan içeriğine
müdahele edebileceğimiz metodları virtual olarak tanımlamalıyız. Virtual metodlara, bu
metodların bulunduğu sınıftan türemiş sınıflarda müdahele edilebilir. Örnek olarak canlılar
sınıfımızda "TurYaz" adında canlının türünü ve yaşını return eden virtual bir metodu olsun.

public virtual string TurYaz()


{
return tur+" "+yas.ToString();
}

Şimdi, "Canlılar" sınıfından "Insan" sınıfını türetelim. Sınıf isminden sonra ":" koyup
türeteceğimiz sınıfın ismini yazıyoruz. Unutmamak gerekir ki bir sınıf ancak bir tek sınıftan
türeyebilir. Çoklu kalıtım için ilerleyen satırlarda değineceğimiz arayüzler(Interface)
kullanılır.

class Insan:Canlilar
{

"Insan" sınıfını "Canlilar" sınıfından türettik. Artık "Insan" sınıfımız da yukarıda "Canlilar"
sınıfı için yazdığımız "Tur" ve "SinifBilgisi" özellikleri ile "YasHesapla" ve "TurYaz"
metodlarına sahiptir. Bu üyeler static tanımlanmadığından direkt erişilemezler. Öncelikle
"Insan" sınıfından bir kopya oluşturmamız gerekmektedir. Hem buna hemde virtual
metodların içeriğine müdahele edilmesine örnek olarak "Insan" sınıfımzıda "TurYaz"
metodunu override edelim.

class Insan:Canlilar
{
private string ad;
public override string TurYaz()
{
Insan yeni = new Insan();
yeni.Tur = "Insan";
return "Bu canlı " + yeni.Tur+".Adı "+ad;
}
public string Ad
{
get { return ad; }
set { ad = value; }
}
}

İnsan sınıfının bir kopyasını oluşturduk. Bu şekilde "Tur" özelliğine erişebildik. Intellisense
özelliği ile bunu gözlemleyebiliriz.
1.Şekil: Static tanımlama

Yukarıdaki koda geri dönersek, görüldüğü gibi "Insan" sınıfında "Tur" adında bir özellik
tanımlamamamıza rağmen bu özelliği "Canlilar" sınıfından miras aldığı için kullanabiliyoruz.
"Canlilar" sınıfından miras aldığı özellikler yanında sınıfımıza "Ad" adında yeni bir özellik
ekledik. Yani sınıflarımıza türettiğimiz sınıfın özellikleri yanında yeni özellikler, fonksiyonlar
vs. ekleyebiliriz. "TurYaz" metodunu "Canlilar" sınıfında tanımlamıştık ve kalıtım yolu ile
"İnsan" sınıfına aktarmıştık. "Insan" sınıfından yeni bir üye tanımladığımızda ve "TurYaz"
metodunu kullanmak istediğimizde ne olacak? Bu metodu kullandığımızda "Canlilar"
sınıfındaki metodumuzda yazdığımız işlemler gerçekleşmeyecektir. Sebebi bu metodu "Insan"
sınıfında override etmemizdir. Dolaysı ile "TurYaz" metodunu kullandığımızda yukarıda da
görüldüğü gibi "Bu canlı " + canlının türü+".Adı "+canlının adı" katarı return edecektir.
"Insan" sınıfından türeyen üçüncü bir sınıf daha yazalım.

class Mustafa:Insan
{
public static void AdYaz()
{
Insan yeni = new Insan();
yeni.Ad = "Mustafa ÖZEN";
MessageBox.Show(yeni.TurYaz());
}
}

"Mustafa" sınıfı "Insan" sınıfından türemektedir. "AdYaz" adında bir metoda sahiptir. Bu
metod içerisinde insanın adını bildiriyoruz. Bir mesaj penceresinde "TurYaz" metodunu
çalıştırıyoruz. Bu satırda yukarıda override ettiğimiz metod çalışacaktır. Bu metod içerisinde
canlı türünü "insan" olarak belirlemiştik. Geriye "Bu canlı insan.Adı Mustafa ÖZEN" stringi
return edecektir. Dolaysı ile mesaj penceresinde bu yazı görüntülenecektir. Bunun gibi
.NET'in virtual metodlarını da override edebiliriz. Örnek olarak sıklıkla kullandığımız
ToString() metodu sanal bir metoddur. Dolaysı ile override edebiliriz. Örnek olarak "Mustafa"
sınıfında bu metodu;

public override string ToString()


{
return "ToString metodu override yapıldı.";
}

şeklinde override edersem bu sınıfta ve bu sınıftan türetilen sınıflarda ToString() metodunu


kullandığımızda "ToString metodu override yapıldı." katarı geriye dönecektir. "Canlilar"
sınıfında "TurYaz" sanal metodunu yazdık. "Insan" sınıfında override ettik. "Mustafa"
sınıfında kullandık. Peki "Insan" sınıfında "Canlilar" sınıfındaki "TurYaz" metodunu nasıl
kullanabilirim? Yani override edilmiş metodu değil de sanal metodu nasıl kullanabilirim.
Bunun için "base" ifadesini kullanıyoruz. "Insan" sınıfında aşağıdaki metodu yazalım.

public string Turu()


{
return base.TurYaz();
}

Yukarıdaki "Turu" metodunun yaptığı iş taban sınıfın "TurYaz" metodundan dönen değeri
return etmektir.

Son olarak event ekleyelim. Bildiğiniz gibi eventlar belli bir iş sonrasında tetiklenen
metodlardır. Mesela buton tıklandığında Click olayı tetiklenir yada form yüklendiğinde Load
olayı tetiklenir. Bunların dışında kendimiz de event yazabiliriz. Eventlar delegate türünden
tanımlanır. Delegateler program içerisinde bir yada daha fazla metodu gösteren referans
türünden nesnelerdir. Delegate tanımı aşağıdaki gibidir.

public delegate void Temsilci();

"void" temsilcinin(delegate) temsil ettiği metodun dönüş tipidir. Eğer temsil edilecek metod
dışarıdan parametre alıyorsa bu da temsilcide belirtilmelidir. Mesela string bir değer return
eden ve int türünden bir parametre alan metodu temsil eden delegate aşağıdaki gibi tanımlanır.

public delegate string Temsilci(int sayi);

"Mustafa" sınıfında aşağıdaki gibi küçük bir event oluşturalım.

public string adim;


private delegate void Temsilci();
private event Temsilci Olay;
public void OlayOlustur()
{
Olay += new Temsilci(Mustafa_Olay);
if (adim = = "mustafa")
{
Olay();
}
}
public void Mustafa_Olay()
{
MessageBox.Show("Event çalıştı. ");
}

Önce eventı tanımlayacağımız temsilciyi tanımlıyoruz. Sonra eventı tanımlıyoruz.


"OlayOlustur" adlı metodda önce tanımladığımız eventı oluşturuyor sonra eventı tetikliyoruz.
Sınıf içerisindeki "adim" değişkeni "mustafa" değerini aldığında olay tetiklenmektedir.
Mustafa_Olay() metodu eventımızın çalıştıracağız metoddur.. Başka bir sınıfta;

Mustafa yeni = new Mustafa();


yeni.OlayOlustur();

şeklinde "Mustafa" sınıfının "OlayOlustur" adlı metodunu çalıştırırsak Mustafa_Olay() eventı


tetiklenir ve "Event tetiklendi." mesajı alınır. Bunun gibi herhangi bir işlem gerçekleştiğinde
farklı işlerin tetiklenmesini istediğimizde kendi eventlarımızı yazabiliriz.

Sınıflarımız büyüdükçe takibide zorlaşmaktadır. Sınıfımızda neler kullandığımızı görmek için


sınıfımızda kullandığımız metodları, özellikleri, olayları ve indeksleyicileri bir arayüz
içerisinde tanımlarız. "Canlilar" sınıfımız için aşağıdaki gibi bir Interface yazabiliriz.

interface ICanlilar
{
int YasHesapla(DateTime dogum);
string Tur
{
get;
set;
}
string SinifBilgisi
{
get;
}
string TurYaz();
}

Görüldüğü gibi tanımlamalarda public, private gibi belirteç kullanılmamaktadır.


Arayüzlerdeki tüm üyeler varsayılan olarak public'tir. "Canlilar" sınıfımızı bu arayüzden
türetiyoruz. Arayüzlerden türetilen sınıflar arayüzlerde tanımlanan üyelerin hepsini kullanmak
zorundadır. Yukarıda bir sınıfı ancak tek sınıftan türetebildiğimizi ifade etmiştik. Çoklu
kalıtımı arayüzlerle gerçekleştiriyoruz. Birden fazla arayüz yazıp aşağıdaki gibi bir sınıfı bu
arayüzlerden türetebiliriz.

class Canlilar:ICanlilar,ICanlilarYeni
{
}

Bu makaleden öğrendiklerimizi özetleyecek olursak;

• Sınıf ve sınıf öğeleri (Constructer, Property, Event, Function, Event) tanımlama.


• Erişim belirteçleri(Public, Private, Protected, Internal)
• Virtual metod kullanma ve override işlemi
• Kalıtım
• Arayüz(Interface) tanımlama ve çoklu kalıtım

You might also like