18 Nisan 2012 Çarşamba

C# 'da OOP-4 Encapsulation (Kapsülleme)

Merhaba arkadaşlar..
OOP 'de 3 temel teknik kullanılır:
1- Encapsulation (Kapsülleme)
2- Inheritance (Kalıtım)
3- Polymorphizm (Çok Biçimlilik)
Bu makalemizde arkadaşlar "Encapsulation" tekniğini inceleyeğiz. Bu konuyu incelerken de "field" ve "property" kavramlarını da öğreneceğiz.

Accsess Modifier makalemizde "Kisi" adında bir class oluşturup içinde değişkenler tanımlamıştık.

    public class Kisi
    {
        string _ad;
        string _soyad;
        bool _cinsiyet;
    }

İşte arkadaşlar class içinde tanımlanan değişkenlerime bundan sonra "Field" olarak sesleneceğiz. Bu field 'larıma diğer sınıflardan erişebilmek için field 'larımı "public" tanımlamıştım. Bu çok yanlış bir hareket arkadaşlar. Böyle bir kullanım ile field 'larımı, diğer sınıflara karşı savunmasız bırakmış olurum. Ayrıyetten field 'larıma kuralsız bir değer atanma riski doğmasına yol açarım. Zaten class içerisinde tanımlanan değişkenlerin varsayılan erşim belirleyicisinin "private" olmasının nedeni de budur. İşte arkadaşlar bu field 'larımı "private" tanımlayabilmeliyim, fakat "private" tanımlanmış bu "field" larımı, "public" tanımlanmış bir aracı tarafından kontrol edebileceğim nesnelere ihtiyacım var. Bu nesnelere de "Property" diye sesleneceğiz. Anlamı özellik demektir. Her "field" için bir "property" tanımlamalıyım. İşte arkadaşlar bu tekniğe "Encapsulation" denir.
Neden Kullanılır?
Kontrolsüz veri girişi yapılmasını önler. Bunu da "property" nesneleri, "get" ve "set" metodlarıyla sağlar. Ayrıca bu get ve set metodları sayesinde, nesnelerimi sadece okunabilir ya da sadece yazılabilir tanımlayabilirim. Gelin şimdi field 'larımın property 'lerini oluşturalım.

        public string Ad
        {
            get { return this._ad; }
            set { this._ad = value }
        }
        public string Soyad
        {
            get { return this._soyad; }
            set { this._soyad = value; }
        }
        public bool Cinsiyet
        {
            get { return this._cinsiyet; }
            set { this._cinsiyet = value; }
        }

Örneğimizde görüldüğü gibi her "field" için bir "property" tanımladık ve erişim belirleyicilerini "public" olarak belirttik.

Property nesnelerimi oluşturmanın bir diğer yolu ise hangi field nesnemin property 'sini oluşturacak isem, o field alanımın üzerine sağ tık, "Refactor", "Encapsulate Field" seçeneğini tıklayarak oluşturmaktır. Aşağıda görüldüğü üzere:

Kafanız karışmasın arkadaşlar. Encapsulation 'ın tek cümlelik tanımı:
Encapsulation, erişilemeyen bir alanı, erişilebilen bir alan ile kontrol etmek demektir. Burada erişilemeyen alanım "private" tanımlanan "field" nesnem, erişilebilen alanım ise "public" tanımlanan "property" nesnemdir.

OOP programlama gerçek hayatın yansıması demiştik. Örneğin bir arabanız var ve bir alışveriş merkezine gittiniz. Alışveriş merkezinin otoparkında görevli "valeler" vardır. Bilmeyenler için valelerin görevi, otopark girişinde arabanızı alırlar ve otoparka kendileri bildikleri düzende park ederler. Siz istediğiniz gibi arabanızı otoparka park edemezsiniz. İşte arkadaşlar valeler bizim property 'lerimiz, otopark ise field 'larımız. "Peki araba neyimiz?" sorusunu sorduğunuzu duyar gibiyim. Araba da field 'ımıza atamaya çalıştığımız değerdir. Bu değere de "value" ismiyle sesleneceğiz. Atmaya çalıştığımız diyorum çünkü arabamızı otoparka istediğimiz gibi bırakamayız. Örneğin arabamız LPG'li yani tüplü olsun. Bilindiği üzere tüplü araçlar kapalı otoparklara alınmaz arkadaşlar. O halde bu örnekte bir kısıtlama, bir kural var. Tüpsüz araç girebilir kuralı. İşte arkadaşlar biz de filed 'larımıza atanmaya çalışılan değerlere bir kısıtlama, bir kural getirebiliriz.

Bu söylediğimizi koda dökmek gerekirse bir yas alanımız olsun. "_yas" isminde bir "field" oluşturalım.

        private int _yas;


Field nesnesine ait property nesnesini tanımlarken, property 'nin tipi, yani geriye döneceği değer, field 'ın tipi ile aynı olmalıdır. Çünkü property 'deki metotlar içerisinde "field" nesnesi kullanılacaktır. Peki nedir bu metotlar? Property 'ler "get" ve "set" metotlarından meydana gelirler. Field 'ımın değerini okurken, filed 'ımı kontrol eden "property" 'nin "get" metodu çalışır ve "return" keyword 'u sayesinde geriye "field" 'ın tipinde "field" 'ım değerini döner. "Field" 'ıma değer atanırken, "filed" 'ımı kontrol eden "property" 'nin "set" metodu çalışır. O halde "field" nesneme değer atanırken bir kontrol yapmak istersem, "property" 'min "set" metodunda, bu kontrolümü yapmalıyım. Atanmasını istediğim değeri , "value" keyword 'u ile ifade ederim. İşte buradaki "value", "set" metodunun parametresidir. Yani "field" 'a atanmak istenen değer "value" 'dur, "set" metotu bu gelen değeri yakalar ve "value" 'ya atar.

Şimdi bu "_yas" "field" 'ıma kontrollü veri girişi yapılması için bir kısıtlama getirmek istiyorum. Yaş 0'dan küçük olamaz değil mi? 

        public int Yas
        {
            get { return this._yas; }
            set
            {
                if (value < 0)
                {
                    this._yas = 0;
                }
                else
                {
                    this._yas = value;
                }
            }
        }

Kodlarımızda göründüğü gibi "yas" alanıma "kontrollü" veri girişi sağlanmış oldu. Buradaki "this" keyword 'unu kullanmasak da olurdu arkadaşlar fakat tavsiyemdir kullanın. Kodun daha rahat okunabilmesi açısından önemlidir. Field 'ımın "Kisi" sınıfının "instance" 'ı (örneği) olduğunu belirtiyorum.

Peki eğer ben "yas" alanıma değer atanamasın, sadece alanımın değeri okunabilsin istiyorsam aşağıdaki gibi sadece "get" metoduna sahip bir "property" kullanmalıyım.

        public int Yas
        {
            get { return this._yas; }
        }

Bu kullanım şekli ile alanım, "Read Only" yani sadece değeri okunabilir bir alan olmuş oldu. Böyle kontroller de yapabilriz arkadaşlar. Bunun tam tersi bir kullanım da mümkündür. Yani sadece "set" metodu olan bir "property" tanımlarsam o alanım, "Write Only" -yalnızca yazılabilir- bir alan olmuş olur.

Şimdiye kadar gördüğümüz "property" örnekleri "full property" kullanımıdır. Bir de kısa "property" kullanımı vardır. Fakat bu kullanımda "field" tanımlanmaz. Ve "get", "set" metodlarının ikisinin de bulunması gerekir. Bu "property" nesnesini kullanmanın kısa yolu ise "prop" yazıp iki kere "tab" tuşuna basmaktır. Bu bir "snippet" 'tır. "Snippet" 'lar kod yazarken kolaylık olması açısından önceden tanımlanmış ve bu tanımlara belirli kodlar atanmış kısaltmalardır. Şimdi bir "full property" örneği görelim. Yine yas alanını örnek vermek istiyorum fakat dediğimiz gibi "field" tanımlamadan, sadece "full property" nesnesini yazıyoruz.

        public int Yas { get; set; }

Bu kullanımda "field" yoktur demiştik, fakat arka planda "property" kendi "field" nesnesini oluşturuyor arkadaşlar.


Şimdi formumun "Load" event 'inde "Kisi" nesnemden örnek alalım, neler yapmışız bir bakalım.
Görüldüğü üzere "property" nesnelerim, "zarf tutan el" ikonuna sahiptir. Ben "kisi" sınıfıma bir özellik daha eklemem gerekirse, örneğin "TC kimlik no" bilgisini de tutmak istiyorum, tüm kisiler için ayrı ayrı "TCKimlikNo" field 'ı tanımlamayacağım. Bir "field" ve bir "property" tanımlayarak tüm kişi örneklerinde bunu kullanabilirim. OOP kullanmanın faydaları arasında genişletilebilirlik ve gereksiz yere kod yazmamaktan bahsetmiştik. Burada da bunu çok açık bir şekilde görüyoruz.


Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

6 yorum:

  1. Bu kadar güzel bir anlatımla karşılaşmamıştım. Dilinize emeğinize sağlık.

    YanıtlaSil
  2. Güzel anlatım olmuş teşekkürler...

    YanıtlaSil
  3. Harika Bir anlatım Çok Teşekkürler...

    YanıtlaSil
  4. Evet çok çok güzel bir anlatım olmuş normalde hiç yorum yazmam ama sen bunu haketmişssin süper.

    YanıtlaSil
  5. Evet çok çok güzel bir anlatım olmuş normalde hiç yorum yazmam ama sen bunu haketmişssin süper.

    YanıtlaSil
  6. Izah etme kabiliyyetiniz cok guzel,videoders anlatimlari da yapsaniz iyi olur bencee...next bloglarinizda basarilar dilerim.

    YanıtlaSil