C# ‘ta Kapsülleme, EriÅŸim Belirteçleri ve Polymorphism

c-ders-142Türkçe karşılığına gelirsek kapsülleme demek. Ancak bilgisayar terimi olarak biraz açarsak kapsülleme, yönettiÄŸi kod ve veriyi birbirine baÄŸlayan ve bu ikisini dış kaynaklı karıştırma ve yanlış kullanımdan koruyan bir mekanızmadır. Bu sayede veriyi dış ortamdan koruyan bir ambalaj vazifesi gördüğünü de söyleyebiliriz. Åžimdi kapsüllemeyi biliyoruz da C#’ta yada .Net Framework’ünde ne gibi farklılıklar var diyeceksiniz? Öncelikle .Net Framework’ünde gelen yeniliklerden bahsedelim.

I. EriÅŸim belirteçlerinin(Access Modifiers) varlığı kapsüllemeyi çok daha rahat yapabilmemize olanak saÄŸlar. Bu sayede bir metod veya bir deÄŸiÅŸken anahtar sözcükler(keywords) aracılığıyla sadece önceden belirlenen sınırlar dahilinde kullanılabilir. Yada bunlara belirlenen sınırlar içinden ulaşılabilir. Burada bahsedilen keyword’leri birazdan açıklayacağım. (Tabii ki C#’ta kullanılan keywordleri açıklayacağım. Ve kullanımlarını basitçe anlatacağım.)

II. Özellik(Property) Sahalarının kullanımı (Bunun yapımını ilerde C# kodu ile göstereceğim.) Bu sayede .Net Framework kapsüllemeyi destekler.

III. Soyut sınıf(abstract class) ve soyut metodların(abstract methods) kullanımı. Aslında kalıtım(inheritance) konusunu anlatırken taban sınıfımız(base class) soyut sınıf idi. Onun için bu kısmı sadece açıklayacağım. Örnek vermeyeceğim. Örneği görmek isteyenler miras(inheritance) konusunu anlattığım yazıdaki örneği incelerlerse istedikleri bilgiye ulaşabilirler.

Evet bu kadarlık giriş yeter. Şimdi yukarıda anlattığım 3 maddeyi enine boyuna tartışalım.

I. Erişim belirteçlerinin ne işe yaradıklarından yukarıda bahsettiğim için burada direkt erişim belirteçlerinin neler olduklarını yazalım ve erişim sınırlarını çizelim. Erişim sınırları geniş olandan dar olana doğru bir sıralama yaparsak.

  • public: Bütün her yerden eriÅŸilmek istenen veriler public anahtar sözcüğü ile birlikte kullanılır. Sadece aynı proje içerisinden deÄŸil diÄŸer projeler içerisinden de eriÅŸilebilir.
  • internal: Aynı assembly içindeki tüm sınıflar eriÅŸebilir. Yani public anahtar sözcüğünün sadece aynı proje içinden eriÅŸilebileni. (VB .Net’te ise Friend anahtar sözcüğüne karşılık gelir.)
  • protected: Protected anahtar sözcüğü ile birlikte kullanılan verilere ise sadece bir alt sınıfa kadar eriÅŸilebilir.
  • private: Bu ise sadece tanımlandığı sınıfta geçerli olan veriler için kullanılır.

Ancak kontrollerde(controller) yaygın olan kullanım ÅŸekli kontrollerin dışarıdan eriÅŸilmesi istenen metodlarının(aynı anda diyelim ki 3 tane kontrol’ün belli metodlarının çalışması gerekli olabilir.) public anahtar sözcüğü kullanılan bir metod içinde tanımlanmasıdır. Åžimdi bu durumun nasıl yapıldığını gösteren mini bir örnek kod yazalım. Kodda belirtilen kontrollerin daha önceden tanımlanmış olduÄŸunu düşünelim.

public void ChangeColor(Color color)
{
    this.groupBoxLine.BackColor = color;
    this.groupBoxOutCity.BackColor = color;
    this.groupBoxExternalPriceDetails.BackColor = color;
    this.groupBoxInternalPriceDetails.BackColor = color;
    this.groupBoxUser.BackColor = color;
    this.groupBox1.BackColor = color;
    this.btnAddNewLine.BackColor = color;
    this.btnAddNewUser.BackColor = color;
    this.btnCentralReport.BackColor = color;
    this.btnChangePassword.BackColor = color;
    this.btnDeleteExternalLine.BackColor = color;
    this.btnDeleteInternalLine.BackColor = color;
    this.btnDeleteUser.BackColor = color;
    this.btnExit.BackColor = color;
}

 

Yukarıdaki metod bir renk parametresi gönderilerek çağrıldığı zaman yukarıda yazan bütün (daha öncede private anahtar sözcüğü ile tanımlanmış olduklarını kabul etmiştik.) kontrollerin rengini gönderilen renge değiştirmeye yarıyor. Bu sayede yukarıdaki kontrollerin hepsinin BackColor dışındaki metodları dış dünyadan soyutlanmış oluyor.

Aslında yaptığımız metod public anahtar sözcüğü ile tanımlanmayıp internal anahtar sözcüğü ile de tanımlanabilir. Bu bizim metodun içindeki kontrollere ait BackColor metodlarının dış dünyadan ne kadar soyutlanmasını istediğimiza bağlıdır.

II. Özellik sahaları sınıflara ait özel(private) değişkenlerin aynı metodlar gibi dış dünyaya açılmalarını sağlıyor. Sadece okuma amaçlı dışa açılım yapılabildiği gibi hem okuma-hem yazma amaçlı bir açılım da yapılabilir. Teorik olarak sadece yazma amaçlı da bir açılım olsa da ne kadar mantıklı olur bilmem!!!! Şimdi örneklerimize geçelim.

 

private int currentExNumber = -1;
private int loginStatus = 0;

public int CurrentExNumber //Sadece okuma amaçlı özellik
{
    get
    {
        return currentExNumber;
    }
}

public int LoginStatus //Hem okuma hem yazma amaçlı özellik
{
    get
    {
        return loginStatus;
    }
    set
    {
        loginStatus = value;
    }
}

Şimdi yukarıdaki özellikleri kullanırken nesneadi.LoginStatus ve nesneadi.CurrentExNumber şeklinde kullanabiliriz. Yalnız dikkat etmemiz gereken CurrentExNumber kullanılacağı zaman sadece eşit işaretinin(=) sol tarafında kullanılabilecek olması. Çünkü başta da belirttiğimiz gibi sadece okuma yapabildiğimiz için get metodu var. Zaten bir değer atamaya kalkarsak hata verecektir.(Derleme esnasında özelliğin sadece okuma amaçlı olduğuna dair debug penceresinden mesaj verir.) Bu sayede de değiştirilmesini istemediğimiz ama kullanmak zorunda olduğumuz verilerin dış ortamdan hem soyutlanmasına hem de bunların dış ortama belirli izinler dahilinde açılımına izin vermiş olduk.

III. Aslında soyut sınıf ve soyut metod’dan daha önce az da olsa miras konusunu anlatırken bahsetmiÅŸtim. Ancak ÅŸimdi biraz polymorphism’den bahsederek bu kavramları biraz daha açacağım. Polymorphism kapsülleme ve miras’dan ayrı düşünülemez. Polymorphism Yunancada “çok formluluk” anlamına gelmektedir. Polymorphism ile soyut sınıf arasındaki ilÅŸkiden bahsetmeden önce soyut sınıf ve soyut metodlarla ilgili bir iki ayrıntı daha verelim. Soyut sınıf sadece taban sınıflarında kullanılır ve yeni nesne yaratılmasında kesinlikle kullanılamaz. (Yani new anahtar sözcüğü kullanılamaz.)

Soyut metodlara gelince bunların ise soyut sınıflarda kullanılacağından bahsetmiÅŸtik. Bunun bize saÄŸladığı avantaj bu metodların türetilen sınıflarda nasıl gerçekleÅŸtirildiÄŸini bilmek zorunda olmamamızdır. Aslında bunu söyleyerek polymorphism’in yararından bahsetmiÅŸ olduk. Yani polymorphism veri soyutlaması yaparak sadece ilgilenmemiz gereken olaylar ve verilerle ilgilenmemize olanak saÄŸlıyor. Bu sayede taban sınıfından türetilen ve aynı metodu farklı gerçekleÅŸtirimlerle(implementation) kullanan birden fazla sınıfa sahip olabiliyoruz. En basit örnek üçgen bir çokgen, kare de bir çokgen ve her ikisinin de bir alanı mevcut. Hemen basitçe bir taslak çıkarırsak çokgen sınıfı soyut taban sınıfı ve alan adında soyut bir metoda sahip. Üçgen ve kare sınıfları ise türetilen sınıflar ve alan metodunu istedikleri biçimde gerçekleÅŸtiriyorlar. (Bu iÅŸlemlerin nasıl yapıldığı miras konusunu anlattığım yazıda mevcuttur.)

Bir de soyut özellikler(abstract property) var. Bunların kullanımı ise soyut metodlar ile özelliklerin birlikte kullanımı ile ortaya çıkmakta. Buna bir örnek kod verirsem anlaşılması daha kolay olacaktır. Ancak bunların kullanımına çok sık rastlamadığımı belirtmem gerekir.

Sanırım aşağıdaki örnek kod parçası soyut özelliklerin kullanımını daha da netleştirmiştir.

abstract class Taban // Soyut sınıf
{
    protected int CurrentExNumber = -1;

    public abstract int GetCurrentExNumber// Soyut özellik
    {
        get;
    }
}

class Turet: Taban //Turet adlı bir sınıf türetiliyor
{

    public override int GetCurrentExNumber// overriding property
    {
        get
        {
            return CurrentExNumber+1;
        }
    }
}

Polymorphism’den bahsettik. Åžimdi ise yalancı polymorphism’den bahsedelim. Aslında bir örnekle biraz daha açarsam daha net olur. Diyelim ki bir karşılaÅŸtırma metodunuz var ve hem integer hem de string veri tiplerini karşılaÅŸtırmak istiyorsunuz. Yalancı polymorphism sayesinde aynı isimde iki metod yazarak bu isteÄŸinizi gerçekleÅŸtirebilirsiniz. Bunun için mini bir örnek kod yazalım isterseniz.

Aşağıda yazacağım metodların aynı sınıf içinde yazıldığını düşünelim. Şimdi bu metodları kullanırken metodların içinde yer aldığı sınıftan üretilen nesneninadi.karsilastir( yazdığımız anda kod tamamlayıcısı bize iki seçenek sunar biri bu metodun iki tane integer veri tipi ile çalıştığı, ikincisi ise bu metodun iki tane string veri tipi ile çalıştığıdır. Bu sayede bir arabirim ile birden fazla metod gerçekleştirilmiş olur.

Aslında bir metodun birden fazla gerçekleştirime sahip olması olayına overloading denir.

Dikkat edilmesi gereken nokta overloading ile overriding’in birbirine karıştırılmamasıdır. Unutmayın overloading’te bütün iÅŸlemler aynı sınıf içerisinde oluyor. Overriding’te ise tek bir sınıf yerine taban sınıfı ile bu sınıftan türetilen sınıflar iÅŸin içine giriyor.

public void karsilastir(int sayi1, int sayi2)
{
    //Metodun iç implementasyonunu sizlere bıraktım.
}

public void karsilastir(string data1, string data2)
{
    Metodun iç implementasyonunu sizlere bıraktım.
}

Kategoriler: C# Programlama, Yazılım

Tags: , , ,

Yorumlar

Yorum Yok

Yorumunuzu Ekleyin

Yorum eklemek için giris yapmalısınız.