Nesne yönelimli programlama (OOP), yazılım geliştirmenin temel paradigmalardan biridir. C#, bu paradigmayı destekleyen zengin bir dil olarak karşımıza çıkar. Bu yazıda, OOP’nin temel kavramlarını ve C#’daki uygulamalarını ayrıntılı bir şekilde ele alacağız.
1. Sınıflar ve Nesneler
Sınıflar (Classes)
public class Kedi
{
public string Isim;
public int Yas;
public void Miyavla()
{
Console.WriteLine("Miyav!");
}
}
Bu örnekte, Kedi
adında bir sınıf tanımlanmıştır. Bu sınıfın Isim
ve Yas
adında iki özelliği (alanı) bulunmakta ve Miyavla
adında bir metoduna sahiptir.
Nesneler (Objects)
Kedi benimKedim = new Kedi();
benimKedim.Isim = "faruk";
benimKedim.Yas = 3;
benimKedim.Miyavla(); // Miyav!
Burada, Kedi
sınıfından bir nesne (benimKedim
) oluşturulmuştur. Bu nesnenin Isim
ve Yas
özellikleri atanmış ve ardından Miyavla
metodunu çağırılmıştır.
2. Kalıtım (Inheritance)
Kalıtımın Kullanımı
public class Aslan : Kedi
{
public void Kükre()
{
Console.WriteLine("kükredi!");
}
}
Aslan
sınıfı, Kedi
sınıfından kalıtım alır (: Kedi
). Bu, Aslan
sınıfının Kedi
sınıfının tüm özelliklerini ve metodlarını miras aldığı anlamına gelir. Ayrıca, Aslan
sınıfına özgü Kükre
adında bir metod eklenmiştir.
Kalıtımın Kullanımı
Aslan aslanim = new Aslan();
aslanim.Isim = "farukkk";
aslanim.Yas = 5;
aslanim.Miyavla();
aslanim.Kükre();
Bu örnekte, Aslan
sınıfından bir nesne oluşturulmuş ve Kedi
sınıfının özellikleri ile birlikte Aslan
sınıfının özel metodları kullanılmıştır.
3. Kapsülleme (Encapsulation)
Kapsülleme Kullanımı
public class BankaHesabi
{
private double bakiye;
public void ParaYatir(double miktar)
{
if (miktar > 0)
bakiye += miktar;
}
public void ParaCek(double miktar)
{
if (miktar > 0 && miktar <= bakiye)
bakiye -= miktar;
}
public double BakiyeSorgula()
{
return bakiye;
}
}
Bu örnekte, BankaHesabi
sınıfında bakiye
adında özel bir alan bulunmaktadır. ParaYatir
, ParaCek
, ve BakiyeSorgula
adında metodlar, bu özel alanı kontrol eder ve sınıfın dışından erişimi kontrol eder.
4. Çok Biçimlilik (Polymorphism)
Çok Biçimliliğin Kullanımı
public class GeometrikSekil
{
public virtual void Ciz()
{
Console.WriteLine("Geometrik şekil çizildi.");
}
}
public class Daire : GeometrikSekil
{
public override void Ciz()
{
Console.WriteLine("Daire çizildi.");
}
}
public class Kare : GeometrikSekil
{
public override void Ciz()
{
Console.WriteLine("Kare çizildi.");
}
}
Bu örnekte, GeometrikSekil
sınıfında Ciz
adında sanal bir metod bulunmaktadır. Daire
ve Kare
sınıfları ise bu metodları kendi ihtiyaçlarına göre uyarlar (override
eder).
Çok Biçimliliğin Kullanımı
GeometrikSekil sekil1 = new Daire();
GeometrikSekil sekil2 = new Kare();
sekil1.Ciz(); // Daire çizildi.
sekil2.Ciz(); // Kare çizildi.
Bu örnekte, GeometrikSekil
türünden referanslar, farklı türlere (Daire ve Kare) sahip nesneleri tutabilmektedir. Bu, aynı metodun farklı türlere uyarlanabilmesini sağlar ve çok biçimliliği ortaya çıkarır.
5. Soyutlama (Abstraction)
Soyutlama, karmaşık sistemlerin veya nesnelerin özünü anlamak ve temsil etmek için kullanılan bir OOP prensibidir. Bu, karmaşık bir nesnenin önemli özellikleri ve davranışlarına odaklanarak, gereksiz ayrıntıları göz ardı etmemizi sağlar.
public abstract class Sekil
{
public abstract double AlanHesapla();
}
public class Dikdortgen : Sekil
{
public double Uzunluk { get; set; }
public double Genislik { get; set; }
public override double AlanHesapla()
{
return Uzunluk * Genislik;
}
}
Burada, Sekil
adında soyut (abstract) bir sınıf tanımlanmıştır. Bu sınıf, AlanHesapla
adında soyut bir metoda sahiptir. Soyut metotlar, alt sınıflar tarafından implemente edilmek zorundadır.
Sekil dikdortgen = new Dikdortgen() { Uzunluk = 5, Genislik = 3 };
double alan = dikdortgen.AlanHesapla(); // AlanHesapla metodunun implementasyonu çağrılır
Bu örnekte, Dikdortgen
sınıfı, Sekil
sınıfından türemiştir ve AlanHesapla
metodu implemente edilmiştir. Sekil
sınıfı soyut olduğu için doğrudan örneklenemez, ancak alt sınıflarından türetilen nesneler kullanılabilir.
Soyutlamayı kullanarak, genel bir yapıyı belirleyebilir ve bu yapının detaylarını alt sınıflara bırakabiliriz. Bu, karmaşıklığı azaltır ve kodun daha bakımı kolay hale gelmesine olanak tanır.
Bir diğer örnek ise şu şekilde olabilir
using System;
// Soyut bir sınıf tanımlanıyor
public abstract class Ev
{
public string Adres { get; set; }
// Soyut bir metot tanımlanıyor
public abstract void EvTipi();
}
// Ev sınıfından türeyen bir alt sınıf
public class Apartman : Ev
{
public int KatNumarasi { get; set; }
// EvTipi metodu implemente ediliyor
public override void EvTipi()
{
Console.WriteLine("Apartman");
}
}
// Ev sınıfından türeyen başka bir alt sınıf
public class Villa : Ev
{
public int BahceAlanı { get; set; }
// EvTipi metodu implemente ediliyor
public override void EvTipi()
{
Console.WriteLine("Villa");
}
}
class Program
{
static void Main()
{
// Soyut sınıftan türeyen nesneler oluşturuluyor
Ev apartman = new Apartman() { Adres = "Örnek Sokak 1", KatNumarasi = 5 };
Ev villa = new Villa() { Adres = "Bahçe Caddesi 22", BahceAlanı = 500 };
// EvTipi metodu çağrılıyor
apartman.EvTipi(); // Çıktı: Apartman
villa.EvTipi(); // Çıktı: Villa
}
}
Bu örnekte, Ev
adında soyut bir sınıf tanımlanmıştır. Bu sınıf, genel özellikleri (örneğin, Adres
) içerir ve EvTipi
adında soyut bir metoda sahiptir. Soyut metotlar, alt sınıflar tarafından implemente edilmek zorundadır.
Apartman
ve Villa
sınıfları, Ev
sınıfından türetilmiştir. Her iki sınıf da EvTipi
metodunu implemente ederek kendi özelliklerini içerir. Bu sayede her ev tipinin kendine özgü detayları bulunabilir.
Son olarak, Main
metodunda Ev
sınıfından türeyen nesneler oluşturularak, soyutlama konsepti kullanılmış ve her ev tipinin özellikleri doğrudan erişilebilir hale getirilmiştir.