8 Şubat 2011 Salı

Nesne Yönelimli Programlama -2 Encapsulation

Bir önceki makalemizde oluşturduğumuz Ayakkabı class'ını hatırlayalım… Bu class'ın içinde bulunan özellikleri public erişim düzenleyicisi (Access Modifiers) ile tanımlamıştım. Ancak makalemin sonunda, böyle yapmanın çok mantıklı olmadığını, bazı özellikleri kısıtlamam (yalnızca okuma ya da yazma gibi) gerekeceğini belirtmiş, hatta "numarası" özelliğini örnek göstermiştim…
Peki bunu nasıl yapmalı? Nasıl yapsak da, class içindeki üyeleri yalnızca okunabilir ya da yazılabilir hale getirsek? Acaba; bu işlem için metodlara başvursak nasıl olur? Deneyelim… Bu deney için, "markasi" özelliğini kullanalım.
Öncelikle, "markasi" özelliğinin değerini class dışına döndürmesi, bir başka değişle değerinin okunması için public Access Modifier'ı ile bir metod tanımlayacağım. Madem ki metodumu public yaptım, öyleyse "markasi" özelliği "private" olabilir. Ayrıca yazdığımız bu metod doğal olarak geriye string tipinde değer döndürecektir… Öyleyse;
private string markasi;
//"markasi" özelliğinin değerini yalnızca okumak için kullanılacak bir metod:
public string OkuMarkasi()
{
return markasi;
}
Pekala, şimdi sıra geldi deneyin ikinci adımına, yani "markası" özelliğine değer atayacak olan metodu yazmaya… Bunun için de yine public bir void metoda ihtiyacım var ve haliyle özelliğe atayacağım değeri bu metodun parametresi olarak alacağım:
//"markasi" özelliğine yalnızca değer atamak için kullanılacak bir metod:
public void YazMarkasi(string deger)
{
markasi = deger;
}
Bakalım işe yarayacak mı? Class'ımızdan bir nesne oluşturup görelim:
private void Form1_Load(object sender, EventArgs e)
{
Ayakkabi pabuc = new Ayakkabi();
pabuc.YazMarkasi("adidas");
MessageBox.Show(pabuc.OkuMarkasi());
}
Bu kodu çalıştırdığınızda MessageBox'da "adidas" değerini görebiliriz. Bu, YazMarkasi() metodunun doğru bir biçimde çalışarak "adidas" değerini class içinde tanımlanan "markasi" alanına değer atadığını ve ardından OkuMarkasi() metodunun bu değeri geri döndürdüğünü gösteriyor. Böylece biz, class içinde "markasi" alanıyla ilgili istediğimiz gibi çalışabiliriz. İşte bu yaptığımız, OOP' nin en temel prensiplerinden biri olan encapsulation işlemidir. Şimdi gelin biraz koddan uzaklaşıp aslında ne yapmak istediğimizi örneklerle açıklayalım…
Gerçek dünyada sık kullandığımız bir örneği ele alalım; televizyon… Standart bir kullanıcı, televizyon izlerken içinde bulunan transducer (anten aracılığı ile aldığı sinyalleri ses ve görüntüye çeviren parça)'i belirli bir frekans aralığında çalışması için ayarlayabilir mi? Cevap, elbette ki hayır. Biz kullanıcılar, televizyon karşısında, ancak kanal değiştirir, sesini ayarlar, renkliğini ya da parlaklığını değiştiririz. Bu bizim için yeterlidir.
İşte biz de ayakkabı class'ımız için aynı şeyi yaptık… "markasi" alanımızı encapsulate ettik. Peki bu daha kolay yazılabilir mi? Elbette… Gelin şimdi buna bakalım. İkinci deneğimiz, "tipi" alanı olsun…
private string tipi;
//tipi alanının encapsulate edilmesi:
public string Tipi
{
get { return tipi; }
set { tipi = value; }
}
İşte belki de çok sık gördüğünüz – hatta kullandığınız – ama anlamını bilmediğiniz property (özellik) kavramını görüyorsunuz. Burada gördüğünüz; "get", aslında az önce yazdığımız OkuMarkasi() metodunun, markasi alanı için yaptığının tam olarak aynısını tipi alanı için yapıyor. Haliyle "set" de YazMarkasi() metodunun görevini üstleniyor. Burada durup size bir şey söylemek istiyorum. Eminim ki birçok nesnenin herhangi bir özelliğinin intellisense sırasında karşınıza çıkan açıklamasını okurken "Get or Set" kelimeleriyle karşılaşmışsınızdır. Aslında bu açıklama bahsi geçen özellikten değer okuyabileceğinizi ya da yazabileceğinizi anlatmaktadır. Bu da özelliğin nasıl yazıldığı hususunda bize bir ipucu vermektedir. 

Artık, bizim class'ımızın da "Tipi" adında bir özelliği bulunmaktadır…  

 

Bildiğiniz gibi, Visual Studio'nun biz programcılar için, küçük jestleri, kısayolları mevcuttur. Bir alanın encapsulate edilmesininin de böyle bir yolu var. Şimdi gelin bir de bu yola bakalım, sıradaki alanımız, "numarasi" alanı olsun…
private string numarasi;
Bu alanımızın üzerine sağ tıklayalım ve ardından açılan menüden "Refactor" seçeneğini, ve alt menüden "Encapsulate Field…" seçeneğini işaretleyelim. 


Karşımıza çıkan sihirbaz ekranını tamamladıktan sonra SÜRPRİZ! Property'niz hazır.
public byte Numarasi
{
get { return numarasi; }
set { numarasi = value; }
}
Bu noktada durup, bir önceki makalemde de aktardığım bir durumu hatırlayalım. Ayakkabi classımın "Numarasi" özelliğinin dışardan değiştirilmesini istemiyorum. Yani, sadece "okunabilir" olmasını istiyorum. Öyleyse özelliğimizi değiştirelim:
public byte Numarasi
{
get { return numarasi; }
}
Böylece, "numarasi" alanı (field) class dışından yalnızca "get" edilebilecek. İşte bu şekilde tanımladığımız özelliklere "read-only" (yalnızca okunabilir) property diyoruz. Hemen söyliyelim; bunun tam tersi de mümkün. Yani yalnızca "set" edilen, "sadece yazılabilir" (write-only) özellik oluşturmak mümkündür.
Bu property kavramındaki son nokta ise, C# 3.0'da bizimle birlikte oluyor. Hiçbir şekilde alan (field) tanımlamadan direkt özellik tanımlama tekniği. Yalnız, Bu tekniği kullanmanız durumunda, yalnızca-okunur ya da yalnızca-yazılabilir özellik oluşturamazsınız. Başka bir deyişle, bu tekniği kullanarak oluşturduğunuz özellik, hem get hem de set yapısını içermek zorundadır. Bunun sebebi, get ya da set kısımlarının kod bloklarının yazılmamasıdır. Öyleyse, üçüncü deneğimiz, "renk" alanı olsun. İşte özelliği geliyor:
public string Renk { get; set; }
Hemen belirteyim, bu kodun da kısa bir yolu var elbette. "prop" snipped'ini kullanarak (bunu söylemek hoşuma gidiyor; prop tab tab), özelliğinizi oluşturabilirsiniz. 

Kaynak:turkayurkmez.com

Hiç yorum yok:

Yorum Gönder