24
Kas'13

OOP 4: Encapsulation(Sarmalama) (C# ile OOP)

Nesneye yönelik programlama anlayışının ilkelerinden bir tanesi olan encapsulation kavramını incelemeye ve kod örnekleri vermeye çalışacağım. Encapsulation kavramının kısa bir açıklamasına OOP 1 yazımda değinmiştim.

 

Encapsulation, erişim belirleyicileri ile sağlanır. Öncelikle erişim belirleyicilere değinmekte fayda var.

Public Erişim Belirleyicisi

Public erişim belirleyicisi ile işaretlenen elemanlar her yerden erişilebilir olurlar. Yani içinde bulunduğunuz namespace’den erişebilirsiniz ve oluşturduğunuz dll’i kullanan her proje, dll içerisindeki public elemanlarınıza erişebilir.

Private Erişim Belirleyicisi

Private erişim belirleyicisi ile işaretlenen elemanlar sadece tanımlandıkları sınıf içerisinden erişilebilir durumdadırlar. Bu elemanlara sınıf dışarısından, nesne örnekleyerek ulaşmak mümkün değildir.

Protected Erişim Belirleyicisi

Protected erişim belirleyicisi ile işaretlenen elemanlar içinde bulundukları sınıftan ve bu sınıftan kalıtılan sınıflardan erişilebilir.

Internal Erişim Belirleyicisi

Internal erişim belirleyicisi ile işaretlenen elemanlar içinde bulundukları namespace içerisinden erişilebilir.

Protected Internal Erişim Belirleyicisi

Protected internal erişim belirleyicisi ile işaretlenen elemanlar, aynı namespace’de olmasalar dahi kendi sınıflarından kalıtılan sınıflar tarafından erişilebilirler. Protected ve internal erişim belirleyicilerinin or işlemine tabi tutulması olarak düşünülebilir.

Getter ve Setter

Sarmalama kavramının uygulanabilmesi için erişim belirleyicilerin etkin olarak kullanılması gerekir. Yapılması gereken kesinlikle her elemanın public yazılıp geçilmesi değildir. Planlama yapmak ve her elemanı uygun erişim belirleyiciler ile işaretlemek gerekir.

 

Örneğin; Sınıf içerisindeki field’lara direkt olarak erişilebilmesi uygun değildir. Zamanında, tüm field’ları public olan bir sınıf yaptığımızı düşünelim. Daha sonra proje içerisindeki binlerce satırda bu sınıftan nesne örnekleyip field’larını kullandık. Bugün ise field’lardan bir tanesine atama yapmadan önce ufak bir kontrol yapma ihtiyacı duyduk. Şimdi dönüp binlerce satırı değiştirelim… Ya da gelin biz bunu böyle yapmayalım. Field private olsun. Nesne örnekleyip erişmek isteyen de public bir metodu aracı olarak kullansın. Bu metoda da Getter diyelim. Belki de bu field’a atama yapmak da istenebilir. Yine bir public aracı metot olsun ve buna da Setter diyelim.

using System;

namespace Encapsulation
{
    class Tasit
    {
        private string _marka;

        public string GetMarka()
        {
            return _marka;
        }

        public void SetMarka(string marka)
        {
            _marka = marka;
        }
    }
}
Tasit t = new Tasit();
t.SetMarka("Wolkswagen");

Console.WriteLine(t.GetMarka());

Böylece bir kontrol eklenmek istenince getter ya da setter içine kodlamak yeterli olacaktır. Örneğin; markaya bir atama yapmadan önce girilen string boş işe bu atama engellensin.

public void SetMarka(string marka)
{
    if (string.IsNullOrEmpty(marka))
    {
        throw new Exception("Marka boş olamaz.");    
    }

    _marka = marka;
}

Property

Çok sayıda field’ı olan bir sınıf için getter ve setter’ı ayrı ayrı kodlamak karmaşıklığa sebep olur. Getter ve setter için daha derli toplu bir yöntem olan property yazmak bu karmaşaya çözüm olabilir.

class Tasit
{
    private string _marka;

    public string Marka
    {
        get { return _marka; }
        set 
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new Exception("Marka boş olamaz.");
            }
            _marka = value; 
        }
    }
}
Tasit t = new Tasit();
t.Marka = "Wolkswagen";

Console.WriteLine(t.Marka);

Propertyler metotlardan farklı olarak, parametre almazlar fakat value anahtar kelimesini kullanarak atama yapmaya olanak tanırlar. Visual Studio derleyicisi value’nin ilgili field ile aynı tipte olmasını bekler. Aksi taktirde kodu derlemez.

Getter ve Setter İçin Farklı Erişim Belirleyiciler

Bu haliyle propertyler için getter ve setter, varsayılan olarak bir üstünün erişim belirleyicisi ile işaretlenir. Yukarıdaki örnekte property’nin kendisi public tanımlandığı için getter ve setter’ı da public olur. Field’lar için ise erişim belirleyicisi belirtilmezse varsayılanı private erişim belirleyicisidir.

 

Getter ve setter için ayrı erişim belirleyicileri belirtilebilir. Aşağıdaki örnekte getter private ile işaretlenmiş ve sınıf dışarısından field’a okuma yapılması engellenmiştir.

public string Marka
{
    private get { return _marka; }
    public set
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new Exception("Marka boş olamaz.");
        }
        _marka = value;
    }
}

Getter ve setter kullanmayıp property yapısını kullandık. Bu Visual Studio derleyicisinin bize sağladığı bir kolaylık. Kod derlenirken derleyici, yazılan property’i getter ve setter olarak kendi kullandığı uniq isimlerle oluşturmaktadır.

 

Bakıldığında, get ve set yapmadan önce ya da sonra herhangi bir kontrol yapmak istemeyen yazılımcı için property’i bu şekilde yazmak bile zahmetli sayılabilir. Şimdi Visual Studio derleyicisinin işleri nasıl daha da kolaylaştırdığına bakalım. Aşağıda bir property örneği verilmiştir.

public string Model{ get; set; }

Böyle bir property’nin, kod derlenirken, derleyici tarafından bir private field’ı ve public getter setter metotları oluşturulur. Getter ve setter için erişim belirleyicileri burada da tanımlanabilir.

public string Model{ get; private set; }

Metodlar İçin Encapsulation

Encapsulation bir sınıfın tüm elamanları için uygulanabilir. Metotlar için uygulanmış bir encapsulation örneği:

protected void ModelDegistir(string model)
{
    Model = model;
}

Metodlar için erişim belirleyicisi belirtilmezse varsayılanı private’tır. 

Constructor İçin Encapsulation

Constructor için erişim belirleyicisini her zaman public yaparız gibi bir düşünceye kapılmayalım. Ctor için de farklı erişim belirleyicileri kullanılabilir. Örneğin ctor’ı private yaparak ve başka ctor kodlamayarak nesne örneklemelerinin sınıf içerisinde yapılmasını garanti altına alabiliriz.

 

OOP yaklaşımı iyi kavrandıktan sonra bu yaklaşımla hamur gibi oynamak mümkündür:). Tasarım şablonları buna iyi bir örnektir.

Özet

– Encapsulation, nesneye yönelik programlamanın temel taşlarındandır.

– Field’lar private yapılıp field için getter ve setter kodlanarak ileride bu konuda oluşabilecek hamallıkların önüne geçilebilir.

– Getter ve setter kodlamanın hızlı yolu property yazmaktır.

– Erişim belirleyicileri her türden eleman için(property, metod vs.) yazılabilir.

 

İyi Eğlenceler…

Yeni makaleleri E-Mail ile takip edin!