C# Kalıtım

Diyelim ki elinizde A diye bir sınıf var. Ancak B diye bir sınıf daha oluşturmanız gerekiyor. Ancak bu B sınıfının içinde A sınıfındaki özellik ve metotların da bulunması gerekiyor. İşte bu durumda B sınıfını A sınıfından türetmeniz gerekir. Türetme kalıtım yoluyla olduğu için A sınıfının bütün üye elemanları B sınıfına adeta kopyalanır. Daha sonra B sınıfının kendine özel üye elemanlarını yazabiliriz. .Net kütüphanesindeki birçok sınıf birbirlerinden türetilmiştir. Örneğin temel veri türleri dediğimiz byte, int, uint, short, float ve bezerlerinin tamamı object sınıfından türetilmiştir. Bu sayede normalde object sınıfında bulunan ToString() metodunu bu yapı türünden nesnelerde de kullanabilirsiniz. Sınıflar türetilebilmesine rağmen yapılar türetilemez. Ancak bir sınıfın türetilmişinden yapı oluşturulabilir.

Temel Sınıflar ve Türetilmiş Sınıflar

Nesne tabanlı programlama ile problemleri gerçek dünyadakine benzer tarzda nesneler şeklinde modelleyerek çözmeye çalışılır. İnşaat sektöründe bir bina nasıl inşa edilir? Önce projesi çizilir. Sonra bu proje gerçekleştirilir ve bina ortaya çıkar. Nesne tabanlı programlamada da önce sınıflar (bina örneğindeki projeye benzetilebilir) tasarlanır. Bir uygulama çok sayıda sınıf yardımıyla modellenebilir. Bu sınıflardan bazıları temel sınıf bazıları da türetilmiş sınıflardır. Temel sınıf “Ata” sınıf olarak işlev görür. Türetilmiş sınıf ise temel sınıfın özelliklerine sahip olmanın yanında kendisi temel sınıfta bulunmayan yeni özellikler de geliştirebilir. Örneğin, girişte de bahsedildiği gibi bir “okul yönetim uygulaması” geliştirileceği düşünülsün. İşe okuldaki her şey modellenerek başlanır. Okulumuzda değişik rollerde insanlar vardır. Müdür, müdür yardımcısı, öğretmen, memur, hizmetli, öğrenci rolleri sayılabilir. Her insan rolü için ayrı ayrı sınıf oluşturmak yerine “insan” sınıfı oluşturup sonra bu sınıftan “kalıtım” yoluyla “müdür”, “müdür yardımcısı”, “öğretmen”, “memur” ve “öğrenci” sınıfları türetilebilir. Bu örnekte “insan” sınıfı “temel sınıf”, diğerleri ise “türetilmiş sınıf” olarak adlandırılmaktadır.

[csharp]class Insan
{
//temel sınıf üyeleri
}
class Ogrenci : Insan
{
//türetilmiş sınıf üyeleri
}[/csharp]

Örnekte görüldüğü gibi “Kalıtım yoluyla türetme ” : (iki nokta üst üste) işlemci yardımıyla yapılmaktadır. İki noktanın solundaki sınıf (Ogrenci) türetilmiş, sağındaki ise (Insan) temel sınıftır. Burada Ogrenci sınıfı Insan sınıfından türetilmiş bulunmaktadır. Diğer bir ifadeyle Ogrenci sınıfı Insan sınıfının özel (private) olmayan tüm üyelerini kalıtım yoluyla almıştır. Türetme sonucunda Insan sınıfının özel (private) olmayan tüm alanlarını otomatik olarak Ogrenci sınıfı içermektedir.
Bir sınıf doğrudan en fazla bir sınıftan türetilebilir. İki ya da daha fazla sınıftan türetilemez. Eğer böyle bir ihtiyaç olursa arayüzleri kullanmak gerekir. Ancak tüm sınıflar dolaylı olarak System.Object sınıfından türetilmektedir. Bunun belirtilmesine de gerek yoktur. Örneğin üstte oluşturulan Insan sınıfına hiç üye eklenmese bile bazı üyelere otomatik olarak sahip olduğu görülür. Bunlardan bir tanesi ToString metodudur. Aslında bütün sınıflar bu metoda sahip olur. Bu da onların dolaylı olarak System.Object sınıfından türediğini kanıtlar. Aşağıdaki resimde Class View penceresi görülüyor. Insan sınıfının temel sınıfının (Base Types) Object olduğu açıkça görülmektedir.

Sınıf görünümü (class view) penceresi

Sınıf görünümü (class view) penceresi

Türetilmiş bir sınıftan başka sınıflar da türetilebilir. Ancak bunun bir şartı vardır. “Sealed” olarak tanımlanmış bir sınıftan başka bir sınıf türetilemez.

Diğer sınıflar da aynı şekilde,

[csharp]
class Mudur : Insan
{
//türetilmiş sınıf üyeleri
}
class MudurYardimcisi : Insan
{
//türetilmiş sınıf üyeleri
}
class Ogretmen : Insan
{
//türetilmiş sınıf üyeleri
}
class Memur : Insan
{
//türetilmiş sınıf üyeleri
}[/csharp]

türetilebilir.

Temel Sınıf Kurucularını Çağırma

Türetilmiş bir sınıf, temel sınıfın tüm alanlarına sahiptir. Bu alanların başlangıçta ilk değerlerinin belirlenmesi gerekir. Bu amaçla kurucu metotlar çağrılır. Türetilmiş bir sınıftan temel sınıfa ait kurucu metodu çağırmak için “base” anahtar sözcüğü kullanılır.

[csharp]
class Insan
{
//temel sınıf üyeleri
public Insan(string ad)//temel sınıf için kurucu metot
{
//…
}
//…
}
class Ogrenci : Insan
{
//türetilmiş sınıf üyeleri
public Ogrenci(string ad)
: base(ad)//Insan(ad) temel sınıf kurucu metodunu çağırır
{
//…
}
//…
}[/csharp]

Bu şekilde temel sınıf kurucusu çağırılmazsa derleyici varsayılan temel sınıf kurucusunu çağırmaya çalışır. Bu da başarılamazsa bir derleyici hatası oluşur.

Sınıflar Atamak

Bir sınıf türü kullanarak bir değişken bildirmek ve sonra bir nesne yaratarak bu değişkene atamak için aşağıdaki söz dizimi kullanılır. Aşağıdaki hiyerarşik yapıya sahip olunsun.

[csharp]class Insan
{
//temel sınıf üyeleri
public double Boy, Kilo;
public string Ad;
public Insan(string ad)//temel sınıf için kurucu metot
{
this.Ad = ad;
this.Boy = 0.45;
this.Kilo = 3.5;
}
public void Buyu()
{
Boy += 0.5;
Kilo += 0.5;
}
}
class Ogrenci : Insan
{
//türetilmiş sınıf üyeleri
public Ogrenci(string ad)
: base(ad)//Insan(ad) temel sınıf kurucu metodunu çağırır
{
}
new public void Buyu()
{
this.Boy += 1.5;
this.Kilo += 1.5;
}
public void Oku()
{
//Oku metodu kodları
}
}
class Ogretmen : Insan
{
public Ogretmen(string ad)
: base(ad)
{
}
}[/csharp]

Şöyle bir bildirim ve atama gerçekleştirebiliriz:

[csharp]Ogrenci birOgrenci = new Ogrenci(“Ali UZUN”);[/csharp]

Burada birOgrenci değişkeni Ogrenci türünde bildiriliyor ve new sözcüğü ile oluşturulan nesne birOgrenci değişkenine atanıyor.

Programlama dilindeki tür denetim kuralları bir türdeki nesneyi farklı bir türde bildirilmiş bir değişkene atamaya izin vermez.

[csharp]Ogrenci birOgrenci = new Ogrenci(“Ali UZUN”);
Ogretmen birOgretmen = birOgrenci; //hata[/csharp]

Yukarıdaki örnek derleme zamanı hatasına neden olur. Derleyici Ogrenci’nin Ogretmen’e açıkça dönüştürülemeyeceğini bildiren bir hata mesajı görüntüler.
Bunun yanı sıra tür olarak kalıtım hiyerarşisinin üst sırasında yer alan bir türde tanımlanmış bir değişkene alt sıradaki bir türde oluşturulmuş nesne atanabilir. Örneğin,

[csharp]Ogrenci birOgrenci = new Ogrenci(“Ali UZUN”);
Insan birInsan = birOgrenci; //geçerli bir atama[/csharp]

Ogrenci sınıfından tanımlanmış birOgrenci, Insan sınıfından tanımlanmış birInsan değişkenine atanabilir çünkü Insan sınıfı hiyerarşinin üst sırasında yer almaktadır.
Aslında Ogrenci sınıfı Insan sınıfının tüm üyelerine sahip ve sadece birkaç fazlası vardır. diplomaNotu ve Oku üyeleridir. Yalnız üstteki örnekte birInsan değişkeni aracılığı ile sadece Insan sınıfının üyelerine erişilebilir. Yani Ogrenci sınıfındaki Oku metoduna erişmek mümkün olamaz.

New Metodu

Programcının çok zorlandığı durumlardan bir tanesi de sınıflara ve sınıfların üyelerine benzersiz ve anlamlı adlar bulmaktır. Eninde sonunda sınıf hiyerarşisi içerisinde temel sınıfa ait bir metodun adı türemiş sınıfta kullanılacaktır. Örneğin,

[csharp]
class Insan
{
//temel sınıf üyeleri
public double Boy, Kilo;
public string Ad;
public Insan(string ad)//temel sınıf için kurucu metot
{
this.Ad = ad;
this.Boy = 0.45;
this.Kilo = 3.5;
}
public void Buyu()
{
Boy += 0.5;
Kilo += 0.5;
}
}
class Ogrenci : Insan
{
//türetilmiş sınıf üyeleri
public Ogrenci(string ad)
: base(ad)//Insan(ad) temel sınıf kurucu metodunu çağırır
{
}
new public void Buyu()
{
this.Boy += 1.5;
this.Kilo += 1.5;
}
public void Oku()
{
//Oku metodu kodları
}
}[/csharp]

Insan temel sınıfında yer alan Buyu metodu Ogrenci türemiş sınıfında da kullanılmaktadır. Derleyici bu durumda Insan sınıfındaki Buyu metodunun gizlendiğini belirten bir uyarı görüntüler. Bu uyarı aynı zamanda “new” sözcüğünü kullanarak bu uyarının kaldırılabileceğini de belirtir. İşte türemiş Ogrenci sınıfındaki Buyu metodunun başında “new” sözcüğünü kullanma nedeni budur. Burada derleyiciye bilinçli olarak temel sınıftaki Buyu metodunun gizlendiği bildirilmiş olunuyor.

Virtual (Sanal) Metodu

Temel sınıfa ait bir metodun bazen türemiş sınıfta farklı bir şekilde kullanılması gerekebilir. Bu durumda temel sınıfın söz konusu metodu türemiş sınıfın değiştirip kullanabileceği yönünde izin vermesi gerekir. Bu izin, metodun temel sınıfta “virtual” olarak tanımlanması sonucu verilmektedir. Diğer bir ifadeyle temel sınıfta “virtual” olarak tanımlanmış bir metodun türemiş sınıfta yeniden yazılabileceği belirtilmiş olunuyor. Örneğin,

[csharp]
public class Sekil
{
public const double PI = Math.PI;
protected double x, y;
public Sekil()
{
}
public Sekil(double x, double y)
{
this.x = x;
this.y = y;
}
public virtual double Alan()
{
return x * y;
}
}[/csharp]

Sekil sınıfına ait alan adında bir metot olsun. Örnekte alan metodunun “virtual” tanımlandığına dikkat edilmelidir. Sekil sınıfından türeyecek diğer sınıflar içerisinde alan metodunun değiştirilerek yeniden yazılmasına burada izin verilmiş bulunuluyor.

Override (Geçersiz Kılma) Metodu

Temel sınıfta “virtual” tanımlanmış bir metodun türemiş sınıfta yeniden yazılması için (geçersiz kılma) “override” sözcüğü kullanılır. Temel sınıfta “virtual” tanımlanmamış ya da “static” tanımlanmış olan üyeler (metot, özellik, dizinleyici ya da olay) türemiş sınıfta yeniden yazılamaz (Geçersiz kılınamaz.). 1.4 başlığı altında verilen örneği şu şekilde genişletilebilir:

[csharp]public class Daire : Sekil
{
public Daire(double r)
: base(r, 0)
{
}
public override double Alan()
{
return PI * x * x;
}
}
class Kure : Sekil
{
public Kure(double r)
: base(r, 0)
{
}
public override double Alan()
{
return 4 * PI * x * x;
}
}
class Silindir : Sekil
{
public Silindir(double r, double h)
: base(r, h)
{
}
public override double Alan()
{
return 2 * PI * x * x + 2 * PI * x * y;
}
}[/csharp]

Bu örnekte Daire, Kure ve Silindir sınıfları Sekil temel sınıfından türetilmişlerdir. Hepsinde de Sekil sınıfında “virtual” tanımlanan alan metodu yeniden yazılmıştır. Bu yeniden yazma (geçersiz kılma) esnasında “override” sözcüğünün kullanıldığına dikkat ediniz. Ayrıca burada dikkat edilmesi gereken nokta “virtual” ve “override” metotların imzalarının (dönüş türleri ile birlikte parametrelerinin tür ve sayıları) aynı olması gerekliliğidir.
Ayrıca temel sınıfta “virtual”, “abstract” ya da “override” olarak tanımlanmış metotlar türemiş sınıfta geçersiz kılınabilir.
Bir diğer önemli nokta da “override” metotlar “new”, “static” ya da “virtual” sözcükleri ile tanımlanamaz.
Son olarak “virtual” metodun erişim belirteci “override” sırasında değiştirilemez. Yani temel sınıfta metot “public” ise türemiş sınıfta da “public”, “protected” ise “protected” kalmalıdır.

Protected (Korumalı) Erişim

“Protected” sözcüğü bir erişim belirtecidir. Yani bir sınıfın üyelerine kalıtım hiyerarşisi içinde o sınıftan türemiş diğer sınıfların erişebileceğini belirtir. Hiyerarşi dışından ise kimse “protected” üyelere erişemez. Benzer şekilde erişimi denetleyen “public” sözcüğü bir üyeye herkesin erişebileceğini, “private” sözcüğü ise sınıf dışından üyeye kimsenin erişemeyeceğini belirtir. Programlama dili tasarımcıları, sınıflar içerisinde yer alan üyelere erişim konusunda programcılara tam bir özgürlük sağlar. Ancak nesne tabanlı programlama belgeleri alanların “private” tutulmasını, alanlara erişimin özellik adı verilen özel metotlarla yapılmasını önerir.

 

Kaynak: Megep Modülleri

Ahmet Şenlik

Kocaeli Üniversitesinde Bilgisayar Programcılığı okudum DGS ile 2016 yılında Sakarya Üniversitesi Bilgisayar mühendisliğini kazandım. Yazılımla uğraşmayı çok seviyorum bu alanda kendimi daha da geliştirmeyi düşünüyorum. Eğer siz de seviyorsanız bu işi devam edin başlamadıysanız başlayın başaracağınıza inanın. :)

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.