Herkese merhaba. Nesne Yönelimli Programlama Nedir? yazımda -bütün nesne yönelimli programlama dillerine de uygun olabilmesi adına- nesne yönelimli programlamaya kabataslak bir giriş yapmıştım. Şimdi ellerimizi biraz kirletmenin zamanı geldiğini düşünüyorum. 😄 Adım adım bütün OOP konularını C# için ele alacağım. Önce kapsülleme ile başlayalım. Kapsülleme ile bir nesnenin dışarıdan erişilmesini engellemiş oluruz. Bu sayede ilerde bir dll, kütüphane ya da framework geliştirdiğimiz zaman insanlara sadece bizim izin verdiğimiz kadarına erişim hakkı sunarız. Erişim belirleyicilere biraz daha detaylı bir şekilde baktıktan sonra C# içinde kapsülleme işlemini nasıl yapacağımızı göstereceğim.

C# Erişim Belirleyiciler ve Kapsülleme

Erişim Belirleyiciler

C# içerisinde 5 adet erişim belirleyici bulunuyor. Bunlar public, private, protected, internal ve protected internal.

Public: En genel erişim belirleyicisidir. Assembly de dahil olmak üzere her yerden erişebilirliği sağlar. Herhangi bir kısıtlaması bulunmaz.

Private: Tipe özel bir seviyedir. Yani sadece aynı class içerisinden o nesneye erişim sağlayabiliriz. Program içerisinde kesinlikle değişmesini istemediğimiz kritik kısımları private olacak şekilde işaretleyebiliriz. Kalıtım alan tipler içerisinden erişilemez.

Protected: Seviye olarak private ile aynı seviyededir. Private erişim belirleyicisinden farkı sadece kalıtım alan tipler içerisinden ulaşılmasıdır. Bir anlamda public ve private belirleyicilerinin birleşimi olarak düşünebiliriz.

Internal: Sadece assembly seviyesinden erişilebilir. Özellikle DLL dosyaları oluşturmak istediğimizde kullanırız. Aynı assembly seviyesinden erişilip değişitirilebilir ama dışarıdan kullanan birisi erişim sağlayamaz. Kalıtım ile özellik almaya da izin vermez.

Protected Internal:  Protected veya Internal şeklinde çalışır. Tip içerisinde ve tipten kalıtım almış çocuk tiplerde protected özelliği gösterir. Assembly seviyesinde de internal özellik gösterir. Yazdığımız DLL dosyası başka projede kullanılırken tercih edilir. Proje içerisinde DLL’den kalıtım almasına izin veriyorsak kullanırız.

Kapsülleme (Encapsulation)

Kapsüllemenin ana görevi bir nesnenin bazı özellik ve metotlarını başka class ve nesnelerden saklamaktır. Bu sayede nesnelerin bilinçsiz kullanımını engellemiş oluruz. Sınıf içerisindeki alanlara erişmek için öncelikle private tipinde bir field oluştururuz. Daha sonrasında bu değişkene değer atamak ya da değerini geri döndürmek için 2 adet metot oluştururuz. Bu metotları get ve set metotları olarak tanımlarız. Field, get ve set metotlarından oluşan bu topluluğa kısaca property (özellik) diyoruz. Örneğin ağırlık ve hacim olmak üzere iki özelliği olan Elma nesnesini oluşturalım. Bu özellikleri kapsülleme yardımıyla nasıl görüneceğine bir göz atalım.

class Elma
{
    decimal _agirlik;
    decimal _hacim;

    public void SetAgirlik(decimal agirlik)
    {
        if (agirlik > 100 && agirlik < 500)
        {
            _agirlik = agirlik;
        }
        else
        {
            Console.WriteLine("Ağırlık değeri 100 - 500 aralığında olmalıdır");
        }
    }

    public decimal GetAgirlik()
    {
        return _agirlik;
    }

    public void SetHacim(decimal hacim)
    {
        if (hacim > 5 && hacim < 20)
        {
            _hacim = hacim;
        }
        else
        {
            Console.WriteLine("Hacim değeri 5 - 20 aralığında olmalıdır");
        }
    }

    public void GetHacim(string sifre)
    {
        if (sifre == "1234")
        {
            Console.WriteLine("Hacim: " + _hacim.ToString());
        }

        Console.WriteLine("Bu veriyi görme yetkiniz yok");
    }

}

Sınıf içerisinde erişim belirleyicisi ataması yapılmamış olan değişkenler private olarak kabul edilir. Bu nedenle Main içerisinde Elma classını tanımladığımızda _agirlik ve _hacim fieldlarına erişim sağlayamayız. Ancak Get ve Set ile başlayan metotlara dışarıdan ulaşabiliriz.

class Program
{
    static void Main(string[] args)
    {
        Elma elma = new Elma();

        elma.SetAgirlik(770);
        elma.GetAgirlik();

        elma.SetHacim(30);

        elma.SetAgirlik(220);
        elma.SetHacim(10);

        Console.WriteLine("Ağırlık : " + elma.GetAgirlik());
        elma.GetHacim("4523");
        elma.GetHacim("1234");

        Console.ReadKey();
    }
}

İlk metodumuz SetAgirlik(770) değerini fielda tanımlamaya çalışırken if kuralına takılacak ve değer ataması yapamayacak. Bu nedenle ilk GetAgirlik metodumuz ekrana bir şey basamayacaktır. If kuralındakısıta uygun bir ağırlık tanımladığımızda sorunsuz bir şekilde çalıştığını görebiliriz.

Ayrıca GetHacim metodunda yaptığım gibi verinin sadece özel bir şifre girildiğinde görünmesini sağlayabilirim. Bu sayede kendi geliştirdiğim dll içerisinde GetHacim metodunu kullanabilirken, dll başka bir projeye eklendiğinde şifre bilinmiyorsa GetHacim metodu ekrana yetki hata mesajını verecektir.

C# Kapsülleme Yöntemleri

C# içerisinde 3 farklı şekilde property tanımlayabiliriz. İlk yöntem yukarıda da bahsettiğim gibi field tanımlayıp daha sonrasında fielda ait get ve set metotlarını yazmak. İkinci yöntemde ise fieldı yukarıda tanımlayıp get ve set metotlarını tek bir property haline getirebiliriz. Üçüncü yöntem (auto implemented property) C# 3.0 ile hayatımıza girdi. Field tanımı yapılmaksızın property yazmamıza olanak sağlıyor. Özellikle get ve set metotları içerisinde koşul tanımı yapmamıza gerek olmayan durumlarda bu özelliği kullanabiliriz.

class Person
{
    #region 1. Yöntem
    private string _name;

    public string GetName()
    {
        return _name;
    }

    public void SetName(string name)
    {
        _name = name;
    }
    #endregion

    #region 2. Yöntem
    private string _surname;

    public string Surname
    {
        get { return _surname; }
        set { _surname = value; }
    }
    #endregion

    #region 3. Yöntem
    public string EMail { get; set; } //prop yazıp iki kere taba bastığınızda otomatik olarak eklenir.
    #endregion
}

Main metodu içerisinden hepsinin get ve set metodunu çağırabiliriz. Çağırılma yöntemleri birbirinden farklı olsa da işlevsel olarak aralarında çok farklılık bulunmamaktadır.

static void Main(string[] args)
{
    Person person = new Person();

    person.SetName("Marty");
    person.Surname = "McFly";
    person.EMail = "marty@mcfly.com";

    Console.WriteLine("İsim: " + person.GetName());
    Console.WriteLine("Soyisim: " + person.Surname);
    Console.WriteLine("E-Mail: " + person.EMail);


    Console.ReadKey();
}

property-1

Gerçek hayat uygulamalarında propertyler çok sık kullanılır. Diğer OOP kuralları ile birlikte kapsülleme pratiği yaparak kendinizi geliştirebilirsiniz. Bir sonraki yazıya kadar kendinize çok iyi bakın. 😊