Kapsülleme, sınıf içindeki değişkenlere erişimi kaldırmak ya da kısıtlamak için kullanılır. Önemli bir değişkeni public olarak tanımlamak, değişkene yazılımcı tarafından -bilinçli ya da bilinçsiz- müdahaleye açık hale getirir. Bu da sınıf içindeki metotların çalışmasını olumsuz etkileyebilir. Bu gibi durumların önüne geçmek için kapsülleme tekniği kullanılır.

Sınıf içindeki private değişkenlere field (alan) denir. Alanlara sınıf dışından erişimi kontrol eden değişkenlere ise property (özellik) denir.

Şimdi sınıf içindeki alanlarımızı public tanımlamanın nasıl problem yaratabileceğine bakalım.

class Uye
{
    public string ad;
    public int dogumYili;

    public void YasGoster()
    {
        Console.WriteLine("{0}'un yaşı {1}.", ad, 2015 - dogumYili);
    }
}

Yukarıdaki sınıfta ad ve dogumYili değişkenleri public ve doğrudan erişime açık. Yazılımcı yanlışlıkla doğum yılını negatif bir değer olarak atarsa aşağıdaki gibi sorun olucaktır.

Uye uye = new Uye();
uye.ad = "Mahmut";
uye.dogumYili = -1980;

uye.YasGoster();

"Mahmut'un yaşı 3995." çıktısını alacağız. Pratikte hatalı kod yazmadık ama mantıklı bir sonuç ortaya çıkmadı.

Kapsülleme get ve set anahtar kelimeleri ile yapılır. Alanın değerini geriye döndürmek için get, alanın değerini belirlemek için set kullanırız. Şimdi sınıfı aşağıdaki gibi değiştirelim.

class Uye
{
    private string _ad;
    public string Ad
    {
        get { return this._ad; }
        set { this._ad = value; }
    }

    private int _dogumYili;
    public int DogumYili
    {
        get { return this._dogumYili; }
        set { this._dogumYili = value; }
    }

    public void YasGoster()
    {
        Console.WriteLine("{0}'un yaşı {1}.", _ad, 2015 - _dogumYili);
    }
}

Malum değişkenlerimizi private olarak tanımlayıp bu değişkenlere erişimi belirleyen özellikleri public tanımladık. Bu kullanım get-set'in en temel kullanımıdır ve gördüğünüz üzere herhangi bir müdahale yapmadığı için kod çıktısında bir değişim olmayacaktır.

Bu arada this sınıfın kendisini, value set bloğuna gelen (yani atanmaya çalışan) değeri ifade eder.

Şimdi doğum yılı değerini kontrol edelim ve eğer atanan değer 1900 ve 2015 arasında değilse bir hata fırlatalım.

class Uye
{
    private string _ad;
    public string Ad
    {
        get { return this._ad; }
        set { this._ad = value; }
    }

    private int _dogumYili;
    public int DogumYili
    {
        get { return this._dogumYili; }
        set
        {
            if (value > 1900 && value < 2015)
            {
                 this._dogumYili = value;
            }
            else
            {
                throw new Exception("Doğum tarihi mantıklı bir değer olmalı.");
            }
        }
    }

    public void YasGoster()
    {
        Console.WriteLine("{0}'un yaşı {1}.", _ad, 2015 - _dogumYili);
    }
}

Sınıfı güncelledikten sonra ilk baştaki kod bloğunu tekrar çalıştırdığımızda göreceğiz ki; mantıksız bir sonuç üretmek yerine hatalı satır exception fırlatacak.

Kapsülleme Tekniği
Doğum tarihi mantıklı bir değer olmalı.

Bu arada field ve property'lerin aynı veri tipinde olması gerekiyor çünkü get-set bloklarında property'den değer döndürürken ya da alırken field'lar kullanılıyor.

İsterseniz tek bir field'ı ilgilendiren birden fazla property yazabilirsiniz. Doğum yılındaki mantık kontrolünü kalabalık yapmasın diye kaldırdım.

class Uye
{
    private string _ad;
    public string Ad
    {
        get { return this._ad; }
        set { this._ad = value; }
    }

    private int _dogumYili;
    public int DogumYili
    {
        get { return this._dogumYili; }
        set { this._dogumYili = value; }
    }

    public int Yas
    {
        get { return 2015 - this.DogumYili; }
    }
}

Daha önce yazdığımız YasGoster metodu yerine Yas adında bir property oluşturup şimdiki yıldan doğum yılını çıkarıp onu döndürdük. Böylece metodun içeriğini beğenmeyen bir yazılımcı kendi metodunu yazabilir. Örneğin; ekrana basmak yerine veri tabanına kaydetmek isteyebilir. Geliştirile bilirlik açısından böylesi daha sağlıklıdır.

Mesela aşağıdaki gibi deneyebiliriz.

Uye uye = new Uye();
uye.Ad = "Mahmut";
uye.DogumYili = 1980;

Console.WriteLine("{0}'ın yaşı: {1}.", uye.Ad, uye.Yas);

Bu konu bu kadar, çok da karmaşık bir konu olmadığından detaylandırmaya gerek yok sanırım.

İyi akşamlar Türkiye. Her nerede kapsüllüyor ya da kapsülleniyorsanız.