5
Oca'15

Bonus: C# ile Delegate ve Event Kavramları (.NET, C#, C# ile OOP)

Delegeler(delegates) ve olaylar(events), bir durumun gerçekleştiği zamanda bir şeyler yapabilmemize imkan sağlarlar. Bu, her zaman örnek verilen butona tıklanması veya bir propertynin değerinin değişmesi, yeni bir nesne yaratılması gibi her türlü durum olabilir.

 

Kod normal akışında satır satır işlenir. Biz ise, delegate veya event kullanarak programın çalışma anında bu akışa ortak olan kod blokları oluşturabilmekteyiz. Event, delegelerin özelleşmiş bir halidir.

 

Delegeleri açıklamaya çalışarak devam edelim.

Delegates

Delegeler, bir veya birden fazla fonksiyonu işaret eden işaretçilerdir. Tanımlarında, işaret edebilecekleri fonksiyonların yapılarını barındırırlar.

public delegate int SomeDelegate(string someString);

Yukarıdaki tanımdan “delegate” anahtar kelimesini çıkardığımızda bir fonksiyon tanımından farkı olmadığını görebilirsiniz. Bu delege için public erişim belirleyicisi kullandık. Biliyoruz ki erişim belirleyiciyi burada belirtmeseydik varsayılan olarak private olacaktı.

 

Yine bu yukarıdaki tanım bize, SomeDelegate isimli delegenin, integer tipinden değer döndüren ve parametre olarak bir adet string alan fonksiyonları işaret edebileceğini söylüyor. Madem delegemiz böyle fonksiyonları işaret edebiliyor o zaman biz de böyle bir fonksiyon tanımlayıp nasıl işaret edebileceğine bakalım.

public int SomeFunction(string someString)
{
    ...
}

Delegemizin bu fonksiyonu işaret etmesi için ise aşağıdaki kodu yazmamız gerekiyor:

SomeDelegate someDelegate = new SomeDelegate(SomeFunction);

Tanımladığımız delege tipinden, SomeFunction fonksiyonunu işaret eden bir delege belleğe çıkardık. Bu kod satırından sonra bu delege bellekte yaşadığı sürece ona yeni fonksiyonları da işaret ettirebiliriz. Böylece bu delege birden fazla fonksiyonu işaret etmiş olur.

someDelegate += new SomeDelegate(OtherFunction);

Buradaki OtherFunction fonksiyonunun da interger tipte değer döndürüp bir adet string parametre alan bir fonksiyon olmak zorunda olduğunu unutmayalım.

 

Dikkatinizi “+=” operatörü çekmiş olmalı. Bu operatör ile delegenin daha önceden işaret ettiği fonksiyonları çıkarmadan yeni bir fonksiyonu da işaret etmesini sağladık. “+=” haricinde “-=”, “=” operatörleri de kullanılabilir.

23
Nis'14

OOP 10: Interface Kavramı (C# ile OOP)

Bundan önceki yazımda abstract sınıflardan bahsetmiştim. Şimdi ise abstract sınıfların yakından akrabası olan interfacelerden bahsetmeye çalışacağım. Okuldan mezun olduğumda iş görüşmelerinde karşıma sıkça şu soru çıktı: “Abstract class nedir? Interface nedir? Bu ikisi arasındaki farklar ya da benzerlikler nelerdir?” Bu sorunun ardından biraz boğazımı hafif öksürüklerle konuşmaya hazır hale getirdikten sonra “bildiğim kadarıyla” açıklamaya çalıştım hep. Gelin şimdi o zamanlar bildiğim kadarından biraz daha ileriye gidelim ve boğazımızı ufak öksürüklerle temizleyerek zaman kazanmak yerine, nedir ne değildir anlatalım anlayalım.

 

Interface kelime manası olarak arayüz demektir. Bir arayüzden beklentilerimiz, tabiri caizse asıl yüzeye bir referans sağlamasıdır. Burada asıl yüzeyi class olarak düşünebiliriz. Bir classın bu arayüzü yardımıyla biz o classın yetkinliklerinden kesin olarak haberdar olabilmekteyiz. Nasıl mı? Kural basit. Eğer bir class bir interface tarafından extend edilmiş ise o interface’in zorunlu kıldığı yetkinliklere de sahip olmuş demektir. Mesela foreach ile elemanları arasında bir döngü yapabildiğimiz tüm tipler, IEnumerable interface’inden extend edilmiş olmak zorundalardır. Şimdi daha fazla buraları kurcalamaya gerek yok. Sadece interface isimlendirmesinin “I” ile başladığına dikkat edin. Bu zorunlu olmasa da anlaşılabilirlik açısından güzel bir ayrıntıdır ve interfaceler için genel isimlendirme bu şekildedir.

 

Birkaç kural daha:

– Interfaceler, metod, property, event ve indeksleyiciler barındırabilirler.

– Sadece bir arayüz olduklarından da anlayabileceğimiz gibi, interfaceler elemanlarının gövdelerini barındırmazlar. Sadece tanımları vardır.

– Bir sınıf bir interface tarafından extend edildiğinde o interface’in tüm kurallarına uymak zorundadır. Yani tüm elemanlarını implemente etmek zorundadır.

– Sınıflarda olduğu gibi interfaceler için de tüm erişim belirleyicileri kullanabiliriz.

– Fakat interface elemanları için default erişim belirleyici public’tir. Kendimiz belirlemek istesek de derleyici hata verecektir.

 

Syntax aşağıdaki gibidir:

interface IOrnekInterface
{
    // Metod
    void OrnekMetod();
    // Property
    int OrnekPropery { get; set; }
    // Event
    event EventHandler OrnekEvent;
    // Indexer
    string this[int index]{ get; set; }
}
29
Mar'14

OOP 9: Abstract Kavramı ve Abstract Class (C# ile OOP)

Bu yazımda abstract(sanal) kavramına ve abstract sınıflara değinmeye çalışacağım.

 

Tabiki her şeyden önce böyle bir kavrama neden ihtiyaç duyduğumuzu araştırmak gerekir. Bunun için şimdiye kadar anlattıklarımdan fazlasını içermeyen bir yapı kuralım. Mesela elektronik eşya sınıfı ve bu sınıftan türemiş telefon ve bilgisayar adında iki adet sınıf olsun. İlk ihtiyacımız da bu eşyaların fiyatlarının hesaplanması olsun. Sınıfların içine bu fiyat hesaplama metodlarını da kodlayalım. Sonra ihtiyaçlarımızı biraz daha şekillendireceğiz. Anlatmaya çalıştığım yapının kodları aşağıdaki gibi olacaktır:

class ElektronikEsya
{
    public decimal Alisfiyati { get; set; }
    public decimal KarYuzdesi { get; set; }

    public decimal FiyatHesapla()
    {
        return Alisfiyati + (KarYuzdesi * Alisfiyati);
    }
}

class Telefon: ElektronikEsya { }

class Bilgisayar: ElektronikEsya { }

Main içerisini ise aşağıdaki şekilde kodlayarak telefon ve bilgisayar için fiyat hesaplaması yaptıralım.

static void Main(string[] args)
{
    Telefon telefon = new Telefon() 
    { 
        Alisfiyati = 1100, 
        KarYuzdesi = (decimal)20/100 
    };
    Console.WriteLine("Telefon fiyat: {0}", telefon.FiyatHesapla());

    Bilgisayar bilgisayar = new Bilgisayar() 
    { 
        Alisfiyati = 2000, 
        KarYuzdesi = (decimal)25/100 
    };
    Console.WriteLine("Bilgisayar fiyat: {0}", bilgisayar.FiyatHesapla());
}

Programı çalıştırdığımızda çıktı aşağıdaki gibi olacaktır.

oop9ilkFiyat
Fiyat hesaplama yapabilmek için base classtaki ortak bir metodu kullandık. Her ürün için aynı fiyat hesaplama yöntemi varsa bu iyi bir yol olabilir fakat ürünler için farklı farklı fiyat hesaplama yöntemlerine ihtiyaç duyabiliriz ve tüm ürünler için fiyat hesaplama metodu bir zorunluluk olabilir. Bu durumda base class’taki metodu virtual yapıp child class’ta override edebiliriz ama override etmeme lüksüne de sahibiz:) İstediğimiz, child class’ın bu metodu kullanmaya zorunlu olması. İhtiyacımızı karşılayan anahtar kelime abstract anahtar kelimesidir.

 

Biraz abstract anahtar kelimesinden bahsettikten sonra örneğe devam edebiliriz. Maddeler halinde sıralarsak:

 

– Abstract anahtar kelimesi hem metodlar için hem de classlar için kullanılabilir.

– Bir metodun abstract olarak işaretlenebilmesi için sınıfının da abstract olarak işaretlenmiş olması gerekmektedir.

– Abstract bir sınıf, hem abstract hem de abstract olmayan üyeler içerebilir.

– Abstract metodların gövdeleri ancak child sınıflarda kodlanabilir. Metodların gövdeleri abstract olarak işaretlendikleri abstract sınıflarda kodlanamazlar.

12
Ara'13

OOP 6: Static Kavramı ve Static Elemanlar (C# ile OOP)

Static, adından da anlaşılabileceği gibi “durağan” olmakla alakalıdır. Örneğin static bir değişken belleğe sadece bir defa çıkarılır ve durağandır. Erişmek isteyen herkes aynı adresten okuma yapar. Fakat değerlerini değiştirmek mümkündür. Sabitlerle karıştırılmamalıdır. Sabitlere tanımlandıkları anda bir kereye mahsus değerleri atanır ve değiştirilemez fakat static elemanların değerleri istenildiğinde değiştirilebilir. Daha iyi kavramak için, static elemanların ne tip ihtiyaçlarda kullanılabileceğini inceleyelim.

Static Field ve Static Property

Mesela bir sınıftan kaç adet nesne örneklendiğini bilmek istiyoruz. Belki de bir oto galerimiz var ve adını tek yerde tutmak, her nesne için aynı ada ulaşmak istiyor olabiliriz. Bunlar ve bunlar gibi ihtiyaçlar için static elemanlara başvurmak gerekiyor. Bir elemanı static olarak işaretlemek için static anahtar kelimesini kullanmak yeterlidir.

class OtoGaleri
{
    private static string _firmaAdi;
}

Bu eleman static olmasaydı, otoGaleri sınıfından bir nesne örneklendiğinde _firmaAdi default değeri ile belleğe çıkacaktı. Bir nesne daha örnekendiğinde yine yeni bir _firmaAdi belleğe default değeriyle çıkacaktı. Kısacası ne kadar nesne örneklenirse o kadar da _firmaAdi belleğe çıkacaktır. Fakat _firmaAdi için static anahtar kelimesi kullanıldığında, OtoGaleri sınıfından ne kadar nesne örneklenirse örneklensin bellekte tek bir _firmaAdi elemanı varlığını sürdürecektir. Hal böyle olunca bu elemana nesne örneği üzerinden erişmek, kodu yazanda veya okuyanda yanılgıya sebep olabilir. Aslında static olan bu elemanın sadece bir nesne için değiştiğini düşündürtebilir. Öyleyse mantıklı olan, static elemana tip adı üzerinden erişmek olabilir. C#’ta da static elemanlara erişim tip adı üzerinden yapılmaktadır.

 

Static elemana yalnızca tip adı üzerinden erişilebildiğini gösteren ekran alıntılarını aşağıdan inceleyebilirsiniz.

İlgili sınıf aşağıdaki şekilde kodlanmıştır. Bir static field ve bu fielda erişim sağlayan bir propertyden oluşmaktadır.

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.

Yeni makaleleri E-Mail ile takip edin!