Archive

Archive for the ‘Nesne Yönelimli Programlama’ Category

Nesne Yönelimli Programlama – Polymorphism

06 October 2010 Leave a comment

Merhaba sevgili yazılım aşıkları. Nesne yönelimli programlama konulu eğitsel makale serimize devam ediyoruz. Bu yazımda ele alacağım konu, “çok biçimlilik” olarak türkçeye çevrilebilecek olan ve yine, nesne yönelimli programlama kavramının temellerinden olan polymorphism olacak.

İnanın böyle ciddi cümleler kurmak beni biraz sıkıyor dostlarım. O nedenle, izin verirseniz rahat rahat, geyik yapa yapa size bu kavramı sunmaya çalışacağım (Gerçi, izin vermeseniz de böyle olacak ama neyse).

Sevgilli dostlar, çok biçimlilik kavramını iyi anlayabilmek için miras kavramı hakkında kafamızda hiçbir soru işareti kalmamalı. Eğer o konuda sorun varsa sizi oraya alayım. Şimdi çok biçimlilik kavramını anlamak üzere yine bir nesne modelleyelim isterseniz. Bu kez bir e-ticaret sitesinde, ürün satışı yapmak için kolları sıvıyoruz. Bu e-ticaret sitemiz, sanal market olsun. Yani hem gıda hem de elektronik ürünleri satabilecek bir portal. Site kullanıcısı, satın almak istediği ürünü sepete ekler. Siparişi vermeden önce, sepetteki tüm ürünlerin fiyatları toplanır ve ödenmesi gereken miktar belirlenir. Ha unutmadan, doğal olarak bu ürünlerin KDV oranları da farklı (haydi hayırlısı) olacak ve elbette fiyat ona göre hesaplanacak.

Haydi bakalım. Öncelikle dilerseniz Urun isminde bir sınıf oluşturalım. Site üzerinden satışını gerçekleştirdiğimiz tüm ürünlerin ortak alanları burada olsun.


Sınıf üyelerim gayet basit gördüğünüz gibi. Buradaki amacım, size çok biçimlilik kavramını anlatabilmek olduğu için, diğer sınıflarımın da basit olmasına özen göstereceğim (bazen böyle açıklamaları neden yaptığımı hiç anlayamıyorum. Boşverin takılmayın siz.). Bu sınıfta KDVUygula metoduna dikkat!! Varsayılan olarak, ürün fiyatına %8 oranında KDV uyguluyorum.

Peki gelelim diğer sınıflara. Urun sınıfından Tekstil, CepTelefonu ve kuru gıda ürünlerini temsil edecek sınıflarımı türetiyorum. Evet.. e dedim ya polymorphism’i anlamak için miras kavramını bilmek gerekir diye… Her neyse.

Tekstil:


Cep telefonu:


Ve… Ekmek:


Peki, şimdi de Sepet sınıfımızı yazalım. Bu sınıf, ürünlerimizi taşıyacak ve “ödenmesi gereken tutar” ı bizim için hesaplayacak.


Şimdi, bu makaleyi yazarken, doğru KDV oranlarını bulmak için bu siteye baktım durdum. Ekmeğin KDV oranı %1, cep telefonu %18, tekstil ürünlerinin ise %8. Şöyle kolay hesaplayacağımız örnek fiyatlar vererek, elde etmemiz gereken KDV dahil fiyatları bir görelim. Eğer ekmeğin kdv hariç fiyatı 10 kuruş olsaydı, KDV dahil fiyatı 10 x 1.01 = 10,1 kuruş olacaktı. Peki bakalım bizim şu sınıflar, bu fiyatı hesaplayabilecek mi? Görelim:


..ve sonuç:


Hmm… İşte sorun! Ama bu sorunu, eminim ki teşhis etmişsinizdir. İçinizden diyorsunuz ki, “eh be şişman adam, Urun sınıfındaki KDVUygula metodu varsayılan olarak %8 vergi uygularsa böyle olur”. Peki tamam. Nasıl çözeceğiz o zaman bu sorunu? KDVUygula metodunu Urun sınıfından kaldırmamı beklemeyin. Çünkü tüm ürünlerimde (tekstil,cep telefonu ve ekmek) bu metod var. O zaman şöyle diyebilir miyiz, evet tüm ürünlerde KDVUygula olmalı ama, hepsinde FARKLI çalışmalı! Evet işte şu an da çok biçimli olması gereken bir KDVUygula metoduna ihtiyaç duyuyorsunuz! Hazır bu ihtiyacı duymuşken, şu polymorphism’in tanımını bir yapalım. Temel sınıftan, türetilmiş sınıfa kalıtım yoluyla aktarılan, fakat türetilmiş sınıfta farklı bir şekilde kullanılabilmesine izin verilen sınıf üyesi, çok biçimli bir üyedir. Buraya kadar bu yazıyı okumuşsanız, hala sıkılmamışsınız demektir. Öyleyse, bir şişman adam örneği hakettiniz!

Çok değil bundan bir elli atmış yıl önce, babalarımız dedelerimiz bizden çok daha doğal besleniyorlardı öyle değil mi? Fakat biz, hazır yiyeceklerle biraz daha haşır neşiriz. Peki bu beslenme dediğimiz olay canlıların tümünden bize kalıtımla aktarılan birşey değil mi? Evet ama, kalıtımdan kalıtıma bu beslenme şekli oldukça değişmiş! İşte size, atalarımızdan aldığımız çok biçimli bir metod… Beslenme metodu!

Peki, bu çok biçimliliği kendi sınıfımıza uygulama zamanı geldi. Bakın Urun sınıfımdaki KDVUygula() metoduma ne yapıyorum:


“virtual” anahtar kelimesini ekleyerek metodumun çok biçimli bir metod olduğunu gösterdim. Şimdi de, bu metodun yapısını, türemiş sınıflarımda nasıl değiştireceğime bakalım. Hemen Ekmek sınıfına gidelim ve override kelime sini yazdıktan sonra neler geldiğine bir bakalım:


İşte! KDVUygula orada! Demek ki sadece virtual imzalı sınıf üyeleri override edilebilirler (Bu arada override; çiğnemek,ezmek anlamına gelir ). Biz KDVUygula metodunu seçerek yola devam edelim ve metodun gövde kodunu değiştirelim:


Şimdi az önce yanlış hesapladığını gördüğümüz kodu tekrar çalıştırıyorum. Bakalım sonuç ne olacak:


İşte bu! Çok biçimlilik bir kez daha günü kurtardı. Teşekkürler nesne yönelimli programlama, teşekkürler çok biçimlilik.

Buraya kadar, aklınızda bir soru işareti kalmış olabilir.. Yukarıda override kelimesini “ezmek” olarak tanımlamıştım. Peki kim neyi eziyor? Biraz buraya odaklanalım. Unutmayın ki, bu örnekte tüm ürünlerimde KDV uygulanması gerektiğinden dolayı Urun sınıfına KDVUygula metodunu ekledim. Sepet nesnesinde ödenecek tutarı hesaplarken de urun nesnesinin KDVUygula metodunu kullandım. Yine örnekte sepet.Ekle(Urun urun) metodunu kullanarak bir Ekmek nesnesini, sepete ekledim. Aradaki miras ilişkisi sayesinde bunu yapabildim. Sonuç olarak, Ekmek sınıfı içinde yer alan KDVUygula metodu, Urun içindeki KDVHesapla metodunu geçersiz kıldı yani ezdi. Böylece, ekmek için %1 KDV uygulanması gerektiğini belirtebildim.

İşte sevgili dostlarım. Nesne Yönelimli Programlama dünyasının bu karışıkmış gibi görünen polymorphism konusunun da aslında ne kadar basit olduğunu göstermiş bulunuyoruz. Unutmayın; karmaşık olan şeyler basit geldiğinde, kendimizi geliştirmişiz demektir.

Sağlıcakla kalın.

Yazar:Türkay Ürkmez

Kaynak:turkayurkmez.com

 

Categories: Polymorphism, TÜM YAZILAR

Nesne Yönelimli Programlama – Inheritance

06 October 2010 Leave a comment

Object Oriented makalelerimize (başlıktan da anladığınız üzere) devam ediyoruz. Bu makalemizde, OOP’nin altın kurallarından olan miras kavramından bahsediyor olacağız. Hemen bir ipucu ile başlayalım… Bu miras, tam olarak genetik miras anlamındadır. Yani ebeveynden çocuğa geçen göz rengi gibi. Biz de class’ lar arasında bu tarz bir bağ kurarak bir class içindeki özellik ve metodları, başka bir class’a aktarabiliyoruz. Teknik olarak, miras veren class’a base (temel) class, miras alan class’a ise derived (türetilmiş) class diyoruz.

Inheritance, basitçe bir class’dan başka class’lar türetmektir. Peki, bu bizim ne işimize yarar? Neden bir class’dan başka class’lar türetelim ki? Bu sorunun cevabı, tahmin edeceğiniz gibi günlük hayatta yer alıyor sevgili yazılım aşıkları. Şöyle bir düşünün; insanlar, günlük hayatında kullandıkları nesneleri kategorize eder ve geneller. Ne demek istediğimi şöyle anlatayım; öğlen yemeğinizi bitirdiniz ve iş yerinize dönüyorsunuz. O sırada bir arkadaşınızla karşılaştınız. Arkadaşınız, nereden geldiğinizi sorduğunda ona “kuru-pilav yemekten” demek yerine “öğlen yemeğinden” dersiniz.İşte genellediniz! Veya başka bir örnek şöyle olabilir. Bir bilim-kurgu filmi almaya DVD mağazasına girdiniz. Bu mağaza sizin için ürünleri kategorilemiştir. Mağazadan içeri girdiğinizde Müzik ve Film kategorisi arasında seçiminizi yaparsınız önce. Daha sonra Film kategorisi içinden Bilim-Kurgu kategorisini bulur, oradan da aradığınız filme ulaşırsınız. Bir de bilimsel bir örnek verelim, bilim adamlarının bir çoğu, uzman oldukları alanlarda, genelleme ve özelleştirme yaparlar (Bu noktada inheritance konusunu bilen/duyan bazı arkadaşlar, biyologların canlı-hayvan-memeli-maymun kategorisi gibi bir örnek vereceğimi sanıyorlar ama yanılıyorlar ). Örneğin dil bilimciler (yaaa demedim mi ben?), dünya dillerini üç kategoriye ayırırlar (Tek heceliler,sondan eklemeli diller ve çekimli diller ). Yani genellerler. Ama bir genelleme aynı zamanda özelleştirmedir de, Gidiş yönünüze göre değişir.

Biz de; programlarımızda, bazı nesneleri kategorize etmek isteyebiliriz değil mi? İşte o zaman inheritance’in nimetlerinden faydalanıyoruz. Peki teknik olarak inheritance bize ne katıyor? Gelelim o konuya…

Class’lar arası inheritance uygulamamızın en makul sebebi, “kod maliyetini azaltmak” (yani daha az kod yazmak ) olacaktır. Biraz daha açmak gerekirse; birbirleriyle benzer classları ayrı ayrı yazmak yerine, ortak üyeleri belirleyerek bir base class oluşturmak ve geri kalanlarını bu base’den türetmek çok daha pratik bir çözüm olacaktır.

Biliyorsunuz ki .NET’de tüm tipler object’den türer. Burada bahsedilen türeme de, inheritance konusuna işaret etmektedir. Aşağıdaki resimde object tipinde bir değişkenin metodlarını görmektesiniz:


Peki, inheritance konusunda söylediğim doğruysa ve tüm tipler bu object’den türüyorsa, herhangi bir .NET tipinde de, object metodlarını bulabilmeliyim değil mi?


İşte kanıt! Dilerseniz, siz de başka tipler ile bu testi yapabilirsiniz.

Tamam, .NET kütüphanesinde tüm tiplerin, object tipinden türediğini gözlerimizle gördük. Şimdi sıra kendi tiplerimiz arasında miras uygulamaya geldi.

Aslında bunu yapmadan önce türeten – türetilen ilişkisinin (base-derived) nasıl modellenebileceği konusunda biraz konuşmak istiyorum. Kimin base kimin derived olduğuna nasıl karar vereceğiz? Cevap çok basit! Nesneler arasında, bir tanımlama cümlesi kurabiliyorsanız, aralarında inheritance ilişkisi var demektir. Örneğin:

“Pırasa bir sebzedir” cümlesi, bir tanımlama cümlesidir. Burada iki nesne bulunuyor, “pırasa” ve “sebze”. Demek ki sebze base class, pırasa ise derived class olacaktır. Bir başka bir örnek daha, “Kamyonet bir arabadır”. Dayanamayacağım bir örnek daha vereceğim, “Yazılım eğitmeni bir eğitmendir” ( Bu yaklaşım, ingilizce “… is a …” relationship olarak bilinir. Türkçesi biraz komik duruyor: … bir …. ‘dir. ).

Biz modellememizde, bir restoranın kullanacağı bir yazılımda yer alacak olan class’lar arasında inheritance uygulayacağız. Bir müşteri, restorana gittiğinde masasında hangi çeşitler olur?

Genelleyelim; Yemek, içecek ve tatlı. Şimdi bunları özelleştirelim. Yemek; Et Yemekleri, ara sıcaklar, sulu yemekler. İçecek; alkollü, alkolsüz. Formülümüzü uygulayalım, “Et yemeği (derived) bir yemektir(base)”.

Ohh… Anlattım rahatladım. Hadi yazalım şunu!


İşte yemek class’ım hazır. Şimdi, derived class oluşturalım:


Şişman adam’dan ancak bu kod beklenirdi zaten! Nasıl miras aldığıma dikkat edin; class isminin yanında ‘:’ işareti ve ardından base classımın adı. Peki ne elde ettik? Görelim:


İşte bu! Yemek class’ı içinde yazmış olduğum metod ve özelliklerin tamamı EtYemekleri class’ı na aktarıldı. Böylece ortak olan alanları, genelleme yoluyla ayırabilir ve yemek class’ından istediğim kadar class türetebilirim…

Gördüğünüz gibi dostlarım, nesneler arası ortak olan metodları, özellikleri ve olayları bir base class altında toplayarak; düzenli bir modelleme oluşturdum. Şimdi kavramı daha da iyi anlayabilmek adına, Windows Application platformundan bir örnek vermek istiyorum. Biliyorsunuz ki, Form nesnesi üzerinde bir çok kontrol (TextBox,Button,Label vs.) kullanabilirim. Bu kontrollerin tümünde varolan bazı özellikler var. Mesela, BackgroundColor, Text, ForeColor bunlardan sadece bir kaçı. Bakın Microsoft ne yapmış? Bu ortak özelliklerin tümünü, Control diye bir class içinde toplamış. Sonra Button, Label, TextBox gibi kontrollerin tümünü bu Control classından türetmiş. İşte, bizim de yaptığımız tam olarak böyle bir modelleme…

Söz modellemeye gelmişken, küçük ve güzel bir ipucu vermek istiyorum. Bazen nesneleri görerek tasarlamak işimizi çok kolaylaştırır. Bakın, Visual Studio’da bizim için çok kullanışlı bir class diagram alanı var. Gelin, bir göz atalım:


Solution Explorer penceresinden Projeye sağ tıklatıp açılan menüden View Class Diagram seçeneğini işaretlerseniz, projedek class’larınızın görsel tasarımını görürsünüz. Ben biraz temizlik yapıp aşağıdaki görüntüyü elde ettim:


Bu şekilde, modellemeyi görerek çalışmak, bazen çok daha eğlenceli/anlaşılır/pratik oluyor sevgili arkadaşlar. Kesinlikle tavsiye edilir.

Şimdi, dikkatinizi bir yere çekmek istiyorum… Eminim ki, bir çok okurum, Yemek isimli base class içinde yer alan SunumSekli metoduna dikkat etmişlerdir. İçeriğinde “mevsim yeşillikleri, yanında pilav ile” yazıyor. Peki, menümdeki tüm yemekler aynı şekilde mi sunulacak? Elbette ki hayır. Yani, bazı metodlar ve özellikler; base class’da yazıldıkları gibi kullanılmak zorunda değiller. Peki bu durumu nasıl düzelteceğiz? Her yemeğin bir SunumSekli() vardır ama bunların her birinin içeriği aynı olamaz. Base class’da bulunan Metodun ya da özelliğin, derived class içinde yeniden düzenlenmesi gerekebilir. İşte bu da, polymorphism (çok biçimlilik) konusuna giriyor. Onu da bir sonraki makaleye bırakalım.

Kendinize iyi bakın. Bol nesne modellemeli günler diliyorum.

Kaynak:turkayurkmez.com


 

Categories: Inheritance, TÜM YAZILAR

Nesne Yönelimli Progamlama – Constructor

06 October 2010 Leave a comment

Yine uzunca bir aradan sonra karşınızdayım. Bu bloğu takip eden ve “birşey yazmıyor bu adam” diye bana sitem eden tüm dostlarımdan da özür diliyorum.

Object Oriented hakkında yazdığımız makale dizimizin bu üçüncü bölümünde constructor kavramından bahsediyor olacağım. Bu konuya girmeden önce bir konuya açıklık getirmek istiyorum. Bazı arkadaşlardan ” çok basit konularda yazıyorsun ” diye eleştiriler geldi. Oysa benim amacım zaten bu. Basit ve anlaşılır makaleler yazmak. Web’ de en sık rastlanan sıkıntılardan biri, aranan konunun ya çok teknik bir dille anlatılması ya da temeline inilmeden nedeni anlatılmadan yüzeysel geçilmesi oluyor. Naçizane, özellikle yeni başlayanlara böyle hizmette bulunmaktır amacım.

Bu kısa mesajı verdikten sonra, object oriented hakkındaki üçüncü makalemize geçebiliriz. Bu makalemize bir soru ile başlayalım; nasıl oluyor da bir class’ tan bir nesne türetebiliyoruz? Bu “türetme” işine kod tarafında baktığımızda en sık karşılaştığımız yöntem, “new” anahtar kelimesi kullanmaktır. Örneğin;

Ayakkabi pabuc = new Ayakkabi();

Örnekteki “new Ayakkabi()” kısmı, Ayakkabi class’ı içinde bulunan tüm üyeleri, pabuc isimli nesneye aktarır. Biz bu duruma Ayakkabi class’ından nesne türetmek ya da daha teknik bir ifadeyle instance almak diyoruz. Şimdi, işi biraz daha basit almak istiyorum. Aslında, nesne üretmenizi sağlayan şey class’ ınızın içinde bulunan oluşturucu metot (constructor) dediğimiz üyedir.

Constructor, kesinlikle bir metottur. Ama herhangi bir değer döndüren metot değildir. Ya da void metot olarak da düşünülemez. Constructor, yalnızca üyesi bulunduğu class’dan nesne üretimi sırasında çalışacak olan metoddur. Bu durumda şunu söylemek çok yanlış olmayacaktır, classımdan nesne üretilirken; üyelerin varsayılan değerlerini ayarlamak için constructor kullanırım. Bakınız, Windows uygulaması geliştirirken hep gözümüzün önünde bulunan bir constructor’u inceleyelim şimdi…

Bildiğiniz gibi Windows Form’u aslında bir class. Bakalım bu class’ ın bir constructor’u var mı?

public partial class
Form1 : Form

{

public Form1()

{

InitializeComponent();

}

}

İşte orada! public Form1() ifadesi ile başlayan üye bizim constructor’ ımız oluyor. Şimdi gelin bu tanımı biraz inceleyelim. Gördüğünüz gibi constructor’ un erişim düzenleyicisi (Access Modifier) public. Çoğu constructor’un erişim düzenleyicisi public’ tir. Bunun sebebi, elbette constructor’a class dışından erişilebilir olması gerektiğidir. ( Aksi halde, Form1 frm = new
Form1 ();
diye bir ifade yazamazdık.) Constructor tanımının bir diğer özelliği ise isminin class ismiyle aynı olmasıdır (Form1()). İşte object oriented modellemenin vaz geçilmezi constructor ile böylece tanışmış olduk.

Şimdi, aklınıza bir sorunun takıldığını hissediyorum. Şöyle ki, “geçtiğimiz OOP makalelerinde yazdığımız Ayakkabi class’ ında constructor yazmadığımız halde pabuc nesnesini türetebilmiştik bu nasıl oldu?” Hemen cevaplayalım; Yazdığınız her class’ta varsayılan olarak bir constructor bulunur. Dolayısıyla, siz yalnızca varsayılan ayarları değiştirmek için constructor tanımlarsınız. Belki bu cevap kafanızda bir soru daha oluşmasına neden olacaktır; ‘madem varsayılan olarak bir constructor zaten var o halde neden Form1 classı bir constructor içeriyor? ‘ bunun da cevabını hemen verelim; yukardaki örneğe dikkat ederseniz Form1() constructor’u içerisinde çağırılan InitializeComponent(); isimli bir metot var. Bu metot, Form1.Designer.cs dosyasında bulunan bir metottur ve görevi form üzerinde kullandığımız kontrolleri ve bu kontrollerin özelliklerini oluşturmaktır.

Şunu tekrar belirtelim; constructor, classdan instance alınırken çalışır ve amacı, class üyelerinizin değerlerini ayarlayak nesne referansına geçirir.

Şimdi gelin, bizim meşhur Ayakkabi class’ımıza bir constructor ekleyelim. Hemen kafamızda bir senaryo oluşturalım. Bir ayakkabıcıya gittiniz. Doğru ayakkabıyı alabilmek için, ayakabbıcının bilmesi gereken şey, kaç numara giydiğinizdir öyle değil mi? Sizin elde edeceğiniz ayakkabı nesnesi belirttiğiniz ayak numarasına bağlıdır öncelikle. Madem öyle, işte Ayakkabi class’ımızın constructor’u geliyor:

public Ayakkabi(byte ayakkabiNo)

{

numarasi = ayakkabiNo;

}

Ne mi yaptık? Artık Ayakkabi class’ından nesne üretirken sizden ayakkabiNo parametresinin değerini alacak. Ardından bu değeri class üyelerinden “numarasi” isimli alana (bkz. OOP2 Encapsulation) aktaracak. Böylece “Numarasi” özelliğinin değeri oluşmuş olacak. Haydi… Nesneyi üretirken görelim:


private void Form1_Load(object sender, EventArgs e)

{

Ayakkabi pabuc = new Ayakkabi(44);

}

Görüldüğü gibi pabuc nesnemi üretirken artık numara parametresini girme zorunluluğum var. Şunu da belirtelim ki, constructor’un bir nevi metod olduğunu unutmayın. Bu demek oluyor ki, constructor’lar da overload edilebilirler.

Buradan anlaşılıyor ki, constructor yapısı class tasarımı için vazgeçilmez bir kavram. Aslında söz class tasarımına geldiğinde göre, biraz da bu konu üzerinde duralım.

Class tasarımı dediğimizde, o classı oluşturan üyelerin neler olacağı ve nasıl çalışacağı üzerinde kafa patlatmaktan bahsediyoruz. Doğru tasarlanmış bir class, programcıya çok daha yardımcı olacaktır. Tasarıma ilk olarak, özelliklere ve bu özelliklerin tiplerine karar vererek başlarsınız. Bir özelliğe karar verirken ele aldığınız kriter ilk olarak o özellikle ne yapacağınızdır. Örneğin bizim class’ımızda malzemesi, markasi ve tipi özellikleri arama yapmak için kullanılabilir mi? Evet kullanılabilir. O halde bu özelliklerin tipleri ne olmalıdır? Aklınıza “string” geldiğini hisseder gibiyim. O zaman izninizle biraz kafanızı karıştırmak istiyorum.

Markasi özelliğinin tipini “string” yapmaya karar verdiniz. Sonra kodlama aşamasına geçtiniz ve “Adidas”, “Nike” ile “Camel” markalarından olmak üzere üç farklı nesne ürettiniz. Buraya kadar tamam. Şimdi de bir MarkayaGoreAra metodu yazdınız ve doğal olarak parametresi de string tipinde. Bu metodu test ediyorsunuz; MarkayaGoreAra(“adidas”); yazdığınızda sonuç bulunur mu? Efendim? Bulunur mu dediniz? Üzgünüm yanlış cevap. Sonuç bulunamaz. Ben “Adidas” markalı bir ayakkabı oluşturdum, “adidas” değil. Unutmayın.. case sensitivity öldürür!!

Peki o zaman ne yapacağız? Markasi özelliğinin tipi string olmazsa ne olacak? Acaba kendi tipimizi yapsak nasıl olur? Öyle bir tip yazalım ki, sattığımız ayakkabi markalarını üye olarak içersin. Bu cümleyi okuyan bazı arkadaşlarım enum’dan bahsettiğimi hemen anlayacaklardır. Eğer, belli değerler arasında sınırları olan (Örneğimizde; yalnızca “Adidas”, “Nike” ile “Camel” markaları seçilebilecektir.) tipler oluşturmak istiyorsak enum olarak isimlendirdiğimiz yapıları kullanıyoruz. Hemen bunu örneğimiz üzerinde uygulayarak görelim.

Projemize sağ click / Add / Class diyelim ve “Enums” isimli bir fiziksel dosya ekleyelim. Ardından açılan dosyada namespace alanı içindeki tüm kodları temizleyelim… Ops! Bunu neden mi yaptık? Elbette oluşturacağımız enum tipini farklı fiziksel dosyada tutmak için… Şimdi buraya enum tipimizi yazalım:

public enum MarkaIsimleri

{

Adidas,

Nike,

Camel

}

İşte kendi value-type’ ımızı oluşturduk. Şimdi Ayakkabi class’ı içinde bulunan Markasi özelliğini kendi tipimizle tekrar oluşturalım:

public MarkaIsimleri Markasi { get; set; }

Böylece artık Markasi özelliğine değer aktarırken, belirttiğimiz alanlardan değer seçme özgürlüğüne sahip olacağız. Haydi bunun da fotoğrafını çekelim:


Ya arkadaş, bir programcı daha ne ister? Resmen MarkaIsimleri tipim beni yönlendiriyor: “kardeşim senin sattığın markalar bunlar, seç birini”. Şimdi yukarıda oluşturduğumuz ayyakkabı arama senaryosuna geri dönelim. Artık MarkayaGoreAra metodunuzun parametresi string değil MarkaIsimleri tipinde olacaktır ve doğal olarak siz bu metodu şöyle çağırabileceksiniz; MarkayaGoreAra(MarkaIsimleri.Adidas); . Bakınız güzel bir class tasarlayarak, kendinize iyilik yaptınız. Şimdi class’ imizdaki diğer bazı özellikler için de birer enum yazalım ve ardından Markasi özelliğinde yaptığımız gibi, söz konusu özellikleri yeniden oluşturalım.

Enums.cs :

public enum AyakkabiTipleri

{

Bot,

Çizme,

SporAyakkabi,

Sandalet

}

public enum MalzemeTipleri

{

Nubuk,

Deri,

Suet

}

Ayakkabi.cs:

public AyakkabiTipleri AyakkabiTipi { get; set; }

public MalzemeTipleri Malzemesi { get; set; }

Böylece, basitçe class modelleme konusuna değinmiş olduk. Modelleme konusu elbette bu kadarla sınırlı kalmıyor. Ama konuyu başka makalelere bırakıyorum.

Burada isterseniz constructor konusuna geri dönelim… En son, constructor yapısının da overload edilebileceğini belirtmiştim. O zaman yapalım!

Bir müşteri ayakkabıcıya girdiğinde, “42 numara spor ayakkabı istiyorum” ya da “42 numara deri çizme istiyorum” diyebilir değil mi? İşte bu parametreleri değerlendirerek Ayakkabi class’inin constructor metodunu overload edelim.

public Ayakkabi(byte ayakkabiNo, MarkaIsimleri marka)

{

numarasi = ayakkabiNo;

Markasi = marka;

}

public Ayakkabi(byte ayakkabiNo, MarkaIsimleri marka, MalzemeTipleri malzeme)

{

numarasi = ayakkabiNo;

Markasi = marka;

Malzemesi = malzeme;

}

Eh artık bunun da fotoğrafını çekmek bir zaruret:


İşte dostlarım, constructor metodumuzu kullanarak, nesne üretimini daha verimli bir hale getirmiş bulunuyoruz. Umarım bu konuyu yeterince aydınlatabilmişimdir.

Böylece bir makalemizin de sonuna gelmiş bulunmaktayız sevgili dostlar…

Bir başka makalemizde görüşmek dileğiyle…

C# kardeşliği adına…

Kodla kalın…

Yazar:Türkay Ürkmez

Kaynak:turkayurkmez.com

Categories: Constructor, TÜM YAZILAR

Nesne Yönelimli Programlama-Encapsulation

06 October 2010 Leave a comment

OOP konusundaki eğitsel makalemize encapsulation (kapsülleme) konusuyla devam ediyoruz. Lafı hiç eveleyip gevelemeden konumuza girelim… 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.

Evet sevgili dostlar.. OOP hakkındaki bu ikinci makalemizin sonuna gelmiş bulunuyoruz. Bir sonraki makalede görüşmek dileğiyle…

Kendinize iyi bakın…

Kodla kalın…

Kaynak:turkayurkmez.com


 

Nesne Yönelimli Programlama-Giriş

06 October 2010 Leave a comment

Arkadaşlar, yine uzun zamandan beri yazmayı planladığım bir konuyla karşınızdayım; Nesne Yönelimli Programlama. Yani orijinal ismiyle Object Oriented Programming (iş bu makalede bundan sonra OOP olarak anılacaktır :) C#.NET program geliştirmeye henüz başlayan, ya da tanıştığı ilk programlama platformu .NET olan herkes, bu yapının tamamıyla OOP uyumlu olduğunu duymuştur. Ama nedir bu OOP denen teknik ve neden ona ihtiyaç duyalım?

Her şeyden önce şunu belirtelim, OOP programlama tekniği, tamamen insanı taklit eder. Bu açıdan, yüzyılın en dinamik ve verimli programlama tekniği olarak düşünülebilir. Peki, bu taklit nasıl oluyor? Gelin bunu şişman adamca örneklerle görelim.

Bildiğiniz gibi; dünya üzerindeki ilk insanlar, kendi ihtiyaçlarını kendileri karşılamak zorundaydılar. Yani; kendi barınaklarını kendileri inşa ediyor, kendi av silahlarını, kap, kacak gibi gündelik yaşamlarında ihtiyaç duydukları tüm malzemeleri kendileri imal ediyorlardı. Yüzyıllar sonra, toplumlar oluştukça -ya da yerleşik düzene geçildikçe- insanlar kendilerine özel sorumluluk vermeye başka bir deyişle branşlaşmaya başladılar. Yani berber, kasap, bilim insanı, öğretmen, filozof, doktor, marangoz gibi meslekler ortaya çıktı ve böylece ticaret de ilerlemeye başladı.

Günümüz dünyasında, ihtiyaç duyduğumuz şeylerin hemen hepsini, üreticilerinden elde ediyoruz… Kazmayı küreği alıp evimizi yapmıyoruz ya da arka odadaki elektronik aletlerle kendimize bir LCD televizyon üretmiyoruz. Sorumluluğu vermiş olduğumuz üreticiden gidip satın alıyoruz. İşte teknolojinin bu kadar hızlı gelişmesinin temelinde de bu “branşlaşmanın” yatmakta olduğu çok net bir biçimde gözümüze çarpıyor.

Bu noktaya biraz daha yoğunlaşalım… Bir mucit, bir ürün icat ediyor. Daha sonra bu ürünün seri üretimine başlıyor. Zaman geçtikçe, bu ürüne yeni özellikler ekliyor ve ayrıca, ürünün ilk hallerinde de bulunan işlevleri daha verimli hale getiriyor. Bu ürünün ilk halinde bulunan özelliklere “yeniden kullanılabilir” demek pek de yanlış olmaz sanırım. Ayrıca, ürünün yıllar boyunca geçirdiği değişim de, “geliştirilebilirlik” ilkesini kanıtlamıyor mu?

Şimdi OOP tekniği öncesine bir bakalım… Binlerce satır koddan oluşan yazılım ürünleri. Bu ürünleri geliştiren programcılar; her kodu, her seferinde tek tek yazmak zorunda kaldılar. Muhtemelen bu sebepten dolayı, ürünün versiyonları arasında oldukça uzun bir zaman vardı. Çünkü tasarımdaki en ufak bir değişim (mesela yeni bir menü eklenmesi bile), kodun büyük ölçüde değişmesine neden oluyordu. Bu tam olarak zaman kaybıydı.

Artan yazılım talebi, yeni bir kodlama tekniğini yani OOP tekniğini doğurdu. Tıpkı insanların branşlaştığı gibi, kodları da kendi aralarında görevlerine göre ayırarak bir nevi kod fabrikaları oluşturuldu.

İşte bu fabrikaların adı class (sınıf) olarak biliniyor. Haliyle biz, bu class’lardan nesne üretiyor ve o nesneyi, ihtiyacımız olan her yerde kullanabiliyoruz. İşte dediğim gibi OOP kodlama tekniği, tam olarak insanın şu anki yaşamını taklit eden bir yapı.

Peki bir class’ı nasıl tasarlarız? Neler içereceğine nasıl karar veririz? Bu tamamen üreteceğimiz nesneyi ne amaçla kullanacağımıza bağlıdır. Az önce verdiğim örneklerle düşünürseniz, soruyu bir de şöyle sormamız faydalı olur; Bir fabrikayı nasıl kurarız? Fabrikayı kurma aşamasına geldiyseniz eğer, ne üreteceğinize çoktan karar vermişsiniz demektir değil mi? Öyleyse konu class olduğunda da, öncelikle istediğimiz nesnede hangi özelliklerin olması gerektiğini bilmek durumundayız.

Şimdi, bir proje düşünün. Bu proje, bir ayakkabı satıcısının kullanacağı bir program olsun. Kesinlikle bu projede bir ayakkabı nesnesine ihtiyacınız olacak öyle değil mi? Peki bu ayakkabı nesnesinin özellikleri neler olmalı? Gelin bir liste yapalım…

  1. Markası
  2. Tipi (Bot, spor, çizme vs).
  3. Malzemesi (Deri, süet vs).
  4. Numarası
  5. Rengi
  6. Bağcıklı mı değil mi?

Bu özelliklere karar verdim. İşte class’ ımız (yani fabrikamız) üretilecek olan nesnemizin bu özelliklerini belirlemek durumunda. Hadi o zaman işe başlayalım ve uygun tiplerle classımızı yazalım:

(Aşağıdaki kodlar bir Windows Application projesi içinde yazılmıştır)

Projeye sağ tık, Add New Item, Class diyelim ve aşağıdaki kodları oluşturalım.

class Ayakkabi

{

string markasi;

string tipi;

string malzemesi;

byte numarasi;

string renk;

bool bagcikliMi;

}

Tamam. Şimdi form1′in Form1_Load metodunda, bu class’dan bir nesne üretmeyi deneyelim;


Fakat o da ne? Ayakkabi classımdan ürettiğim pabuc nesnesinde, istediğim özelliklerden hiçbirine erişemiyorum. Çünkü yazdığım özelliklerden hiçbirinin erişim düzenleyicisi (Access Modifier) Public değil! Eğer, class içinde tanımladığınız bir alana class dışından erişmek isterseniz; bu alanı public olarak tanımlamalısınız. Bu durumda, eğer bir proje içinde yazdığınız bir classın başka bir projeden erişilebilmesi için de classın başına public kelimesi getirme zorunluluğumuz ortaya çıkar.

Şimdi, bu değişiklikleri yapalım ve tekrar nesne üretmeye çalışalım:

public class Ayakkabi

{

public string markasi;

public string tipi;

public string malzemesi;

public byte numarasi;

public string renk;

public bool BagcikliMi;

}

Değişiklikler tamam. Peki ya nesnemiz?


İşte şimdi, nesnemde aradığım özellikleri görebiliyorum… Ama burada bir sorun var sanki. Bazı özelliklerin nesne tarafında değiştirilebilmesini kesinlikle istemiyorum. Örneğin ben Ayakkabi fabrikamdan 44 numara olarak ürettiğim ayakkabının sonradan 48 numaraya yükseltilmesini istemem. Fakat bütün değerlerim public olarak tanımlandığından bunu şu an yapabiliyorum! Bu hiç de iyi bir şey değil.

Söz, tam bu noktada encapsulation dediğimiz kavrama geliyor. Ama bu, bir sonraki makalemin konusu olacak. Şimdilik burada bırakıyorum.

Bir daha görüşene kadar kendinize iyi davranın ve kendinize birkaç class tasarlayın. Hepinize iyi çalışmalar ve mutlu seneler…

Yazar:Türkay ÜRKMEZ

Kaynak:turkayurkmez.com


 

Follow

Get every new post delivered to your Inbox.