Friday, December 14, 2012

Arayüzlerin (Interface) Kullanılması (c#)


 .NET sınıfı kütüphanesinde de birçok arayüz bulunmaktadır. Her arayüz çeşitli amaçlar için yazılmıştır. Örneğin System isim alanında bulunan IDisposable arayüzü gereksiz nesne toplayıcısı (garbage collector) için gerekli olabilecek Dispose() metodunun uygulanmasını zorlar. Aynı şekilde System.Collections isim alanında bulunan IEnumarable arayüzü tanımladığımız sınıfların foreach döngü yapısı ile kullanabilmesini sağlar. IEnumarable arayüzü içindeki metotlar ilgili sınıf tarafından uygulanırsa tanımlanan bu sınıf foreach döngüsü ile kullanılabilir. Çünkü foreach döngüsü çalıştırılmaya başlanınca foreach bloğunda kullanılan sınıfn IEnurable arayüzünü uygulayıp uygulamadığını kontol edilir. Eğer bu arayüz uygulanmış ise IEnumarable arayüzündeki metotlar kullanılarak foreach döngüsü işletilir.Bu konumuzda IEnumarable arayüzünün kullanımına bir örnek vereceğiz.

IEnumarable arayüzünü uygulayan bir sınıf foreach döngü yapısı ile kullanılabildiğini söylemiştik. Tabi foreach döngü yapısı ile kullanabileceğimiz bir sınıfın yapısında dizi ya da daha sonra göreceğimiz koleksiyon tabanlı bir yapının bulunması mantıklı olur.


using System;
using System.Collections;

class Koleksiyon : IEnumerable
{
    int[] Dizi;
    public Koleksiyon(int[] dizi)
    {
        this.Dizi = dizi;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new ENumaralandirma(this);
    }

    class ENumaralandirma : IEnumerator
    {
        int indeks;
        Koleksiyon koleksiyon;

        public ENumaralandirma(Koleksiyon koleksiyon)
        {
            this.koleksiyon = koleksiyon;
            indeks = -1;
        }

        public void Reset()
        {
            indeks = -1;
        }
        public bool MoveNext()
        {
            indeks++;

            if (indeks < koleksiyon.Dizi.Length)
                return true;
            else
                return false;
        }

        object IEnumerator.Current
        {
            get
            {
                return (koleksiyon.Dizi[indeks]);
            }
        }
    }
}

public class MainMetodu
{
    public static void Main()
    {
        int[] dizi = {1,2,3,8,6,9,7};

        Koleksiyon k= new Koleksiyon(dizi);

        foreach(int i in k)
            Console.Write(i + " ");

        Console.ReadLine();
    }
}





Bu programı derlediğimizde ekrana

1 2 3 8 6 9 7

yazıldığını göreceğiz.

Programda neler olup bittiğine göz atmak gerekirse, Koleksiyon isimli bir sınıfın yapısındaki Dizinin eleman değerlerini foreach döngüsü ile elde etmek için Koleksiyon sınıfı System.Collections isim alanında bulunan IEnumarable arayüzünü uyguluyor. Dolayısıyla IEnumarable arayüzündeki bütün metotları uygulamalıdır. IEnumerable arayüzünde sadece

IEnumerator GetEnumerator();

metodu ile bildirilmiştir. Bu metot dizinin içerisinde dolaşmak için gerekli olan IEnumerator referansına geri dönmektedir. Bu yüzden bu metot aşağıdaki gibi yazılmıştır.

IEnumerator IEnumerable.GetEnumerator()
{
  return new Enumaralandırma(this);
}

GetEnumerator() metodunun geri dönüş değeri için IEnumerator arayüzünden türetilmiş IEnumaralandırma sınıfı bildirilmiştir. IEnumerator arayüzündeki metot ve özellikler Koleksiyon nesnesi içindeki dizinin elemanlarına erişmek için kullanılacaktır. IEnumerator arayüzünde bulunan üye elemanlar aşağıdaki gibidir.

object Current{
get;
}

bool MoveNext();

Void Reset();

Bu iç elemanında IENumaralandırma sınıfında bildirilmesi gerekir. Current özelliği koleksiyon nesnesinin herhangi bir andaki değerini gösterir. Sade get bloğunu bildirmek yeterlidir. MoveNext() metodu dizi koleksiyon dizisi içinde bir sonraki elemana geçmek için kullanılır. Eğer bir sonraki elemana geçilemiyorsa false deperini geri döner. Reset() metodu ise koleksiyon dizisini herhangi bir andaki değerini ilk elemandan önceki elemana çeker. Yani dizinin indeksi -1 olur.

IEnumaralandırma sınıfının bir tane yapıcı metodu vardır. Bu yapıcı metot ile üzerinde işlem yapılacak Koleksiyon nesnesi alınmaktadır. Yapıcı metot ile aynı zamanda ENumarandırma sınıfındaki indeks değişkenide -1 değerine çekiliyor. Reset() metodunda ise indeks değişkeni bir artırılıyor. Eğer indeks değişkeninin  yeni değeri dizinin boyutundan büyükse false değerini geri dönmektedir. Current özelliğinin object olduğuna dikkat edin. Eper bu özellik object türünden olmasaydı mğmkğn olabilecek tür dönüşümlerini hesaba katmazsak bütün işlemleri sadece Current özelliği ile aynı türden olan diziler üzerinde yapabilirdik.

Açık (Explict) Arayüz Uygulama


C# dilinde arayüzleri uygulamanın bir yolu daha vardır. Explicit Interface Implementation. Bu yöntem daha önce bahsedilen yöntemlerin aşağıdaki kısımlarından kaynaklanmaktadır.

- Açık arayüz uygulama yöntemi ile istenirse türeyen sınıflarda arayüzde bulunan üye elemanlar açık bir şekilde nesneler tarafından erişilemez hale getirilebilir. İlgili üye elemanlarına sadece arayüz referansları ile erişilmesi sağlanır.

- Birden çok arayüz uygulandığı durumlarda eğer aynı isimli üye elemanlar varsa isim çakışmasının önüne bu yöntemle geçilebilir.

Açık arayüz uygulaması yapmak için arayüzün üye elemanları arayüz isimleri ile beraber belirtilir. Aşağıda buna bir örnek verilmiştir.

using System;
using System.Collections.Generic;
using System.Text;

namespace explicitinterfaceimplemetantion
{
  class Program
  {
     static void Main(string[] args)
     {
        Kedi k= new Kedi();
       
        ((IMEmeli).k).Konus();
     }
  }

interface IMemeli
{
   void Konus();
}

class Kedi : IMemeli
 {
   void IMemeli.Konus()
   {
      Console.WriteLine("miyav");
   }
 }
}

Yukarıdaki örnekte de görüldüğü üzere Konus() metodunun çağrılabilmesi için IMemeli arayüzü referansına çevrilmesi gerekiyor. Direkt Kedi nesneleri üzerinden Konus() metodu çağrılamayacaktır. Böylece sınıf nesneleri için arayüz üye elemanları private gibi davranmaktadır. Normal yöntemle bunu yapmak mümkün değildir.

Wednesday, December 12, 2012

Arayüz (Interface) Referansları (c#)


Arayüzler ile referans oluşturulabilir. Bir arayüz referansı tek başına bir anlam ifade etmez. Ancak arayüz
referanslarına kendisini uygulayan herhangi bir sınıf nesnesinin referansı atanabilir. Bu durumda arayüz
referansı ile arayüzde bulunan metot ya da özellikler hangi sınıf referansı tutuluyorsa o sınıf türünden bir
nesne için çağırılabilir.
Bu özelliğine örnek vermek gerekirse aşağıda ArayuzRef arayüzünü uygulayan iki sınıfın bildirimini görüyoruz.
Main() metodu içinde ise ArayuzRef referansına bu iki sınıfın nesne referanslarının nasıl aktarıldığını ve bu
referans üzerinden sınıflardaki metotların nasıl çağrıldığını görüyoruz.

using system;

interface ArayuzRef
{
  void metot1();
}

class Sinif1 : ArayuzRef
{
  puplic void metot1(){
  Console.WriteLine("Ben Sinif1'in metoduyum");
  }
}

class Sinif2 : ArayuzRef
{
  puplic void metot1(){
  Console.WriteLine("Ben Sinif2'nin metoduyum");
}

puplic class MainMetodu
{
  puplic static void Main()
  {
    ArayuzRef a;

Sinif1 sinif1 = new Sinif1();
Sinif2 sinif2 = new Sinif2();

a = sinif1;
a.metot1();

a = sinif2;
a.metot1();
   }
}

Programı derleyip çalıştırdığımızda ekrana

Ben Sinif1'in metoduyum
Ben Sinif2'nin metoduyum

yazacaktır. Arayüzlerdeki referans aktarma işlemi ile kalıtımda gördüğümüz temel sınıf referansına türeyen sınıf referansı aktarma işlemi ile aynıdır.

Monday, December 10, 2012

Arayüzlerin (Interface) Uygulanması (c#)


 Şimdi bir sınıfın belirlediğimiz bir arayüzün nasıl uygulandığını inceleyeceğiz.
Arayüzlerin uygulanması, sınıfların türetilmesi ile aynı şekilde yapılır. Arayüz uygulamada, arayüzler türetmedeki temel sınıf yerine geçer. Buna göre IArayüz'ü uygulayan Sayılar sınıfı aşağıdaki gibi bildirilir.

class Sayılar : Iarayuz
{
  //uygulanacak elemanlar
}

Sayılar sınıfı bu şekilde IArayuz'den türetildiğinde IArayuz'deki bütün üye elemanları uygulanmalıdır.

Buna göre Sayılar sınıfı IArayuz'ü ile aşağıdaki gibi bildirilebilir.

interface IArayuz
{
 int BirSonraki();
 void Sıfırla();

 int Deger
 {
  get;
  set;
 }

 int this [this indeks]
 {
 get;
 }
}

class Sayılar : IArayuz
{
 puplic int BirSonraki()
 {
   //metot gövdesi
 }

puplic void Sıfırla()
{
  //metot gövdesi
}

puplic int Deger
{
get
{
  //get bloğu
}

set
{
 //set bloğu
}
}

puplic int this[this indeks]
{
get
{
  //get bloğu
}

set
{
 //set bloğu
}
}
}

 Sınıflar arasında çok türetme olmamasına rağmen sınıflar birden fazla arayüzüde uygulayabilir. Uygulanacak
arayüzler virgül ile belirtilir. Örneğin IDisposable ve System.Collecitons isim alanında bulunan IEnumarable
yüzünü uygulayan sayılar sınıfı aşağıdaki gibi bildirilebilir.

using System;
using System.collections;

class Deneme : IDisposable, IEnumerable
{
  //Sınıf elemanları
}

Bir arayüzdeki elemanlar içsel olarak puplic olduğu için arayüzü uygulayan sınıfın arayüzdeki elemanları puplic
olarak bildirilmemelidir.

Bir arayüzü uygulayan sınıfın, sadece arayüzdeki elemanlara sahip olabileceği anlamına gelmez. Aynen türetmede
olduğu gibi arayüzdeki elemanların dışında istenildiği kadar yeni eleman eklenebilir.

Sınıflar birbirlerinden nasıl türetilebiliyorsa Arayüzler de birbirlerinden türetilebilir. Temel arayüzdeki bütün
elemanlar türeyen arayüze aktarılır. Böylece istediğimiz kadar eski arayüzü kullanarak daha geniş arayüzleri
oluşturabiliriz. Aşağıda iki arayüzün türetilmesine ilişkin bir örnek verilmiştir.

interface TemelArayuz
{
 void Metot1();
}

interface TureyenArayuz : TemelArayuz
{
  void Metot2();
}

Arayüzden yeni bir Arayüz türetildiğinde dikkat edilmesi gereken hususlar:

Bu kullanım ile TemelArayuz'ü uygulayan bir sınıf sadece Metot1'i uygulamalı iken TureyenArayuz'ü uygulayan bir
sınıf hem Metot1() hem de Metot2()'yi uygulamalıdır. Aksi halde derleme hatası alınır. Sınıflardan farklı olarak
arayüzleri birden fazla arayüz ile türetebiliriz. Örneğin aşağıdaki Arayuz3 bildirimi tamamen geçerlidir.

interface Arayuz1
{
  void Metot1();
}

interface Arayuz2
{
  void Metot2();
}

interface Arayuz3: Arayuz1, Arayuz1
{  void Metot3();
}

Arayüzleri türetirken new anahtar sözcüğü kullanılarak temel arayüzdeki bir eleman gizlenebilir. Bu şekilde
türeyen arayüzde temel arayüzdeki bir elemanla aynı isimli eleman bildirilebilir.

interface Arayuz1
{
  void Metot1();
}
interface Arayuz2 : Arayuz1
{
 new void metot1();
}

Peki bu durumda sadece Arayuz2'yi uyguluyan bir sınıfta Metot1() metodu uygululandığında geçerli bir bildirim olur mu?
 Hayır, çünkü Arayüz1'deki Metot1() metodu gizlenmiş olsa da kalıtım yolu ile Arayuz2'ye aktarılmıştır. Bu yüzden Arayuz2'yi uygulayan bir sınıf hem Arayuz1.Metot1() hem de Arayuz2.metot1() metodunu uygulamak zorundandır. Bunun için Arayuz_adı.Metot_adı ile hangi arayüzdeki metodu uyguladığımızı bildirmeliyiz. Örneğin;

class Deneme: Arayuz2
{
  void Arayuz1.Metot1();
  {
  }

  void Arayuz2.Metot1();
  {
  }
}

Deneme sınıfından bir nesne üzerinden Metot1() metoduna erişmemiz mümkün değildir, çünkü

deneme d= new deneme();
d.Metot1();

deyimiyle hangi arayüze ilişkin metodun çağrıldığı belirsizdir. Bu yüzden yukarıdaki gibi bir kullanım hatalıdır.

O halde Arayuz1.Metot1() ve Arayuz2.Metot1() metotları sadece Deneme sınıfında aşağıdaki gibi tam yolu
belirtilerek kullanılabilir.

void Arayuz2.Metot1()
{
   Arayuz1.Metot1();
}



Sunday, December 9, 2012

Arayüzler (Interface) (c#)


Özet metotlar ile bir özet metodun bulunduğu sınıftan türeyen bir sınıfın mutlaka bu özet metodu devre dışı bırakıp kendine göre uygulaması gerekirdi. Burada amaç aslında bir sınıfın neye benzediğini tespit etmekti. Özet metotlar sayesinde biliyoruz ki bir önceki temel sınıftan türeyen tüm sınıflarda özet metot uygulanmıştır. Bu da tek bir arayüzle birçok iş yapabileceğimiz anlamına gelir. Yani özet sınıfının bir kısım elemanları kendisinden türeyecek sınıflara arayüz niteliği taşımaktadır. Ayrı bir veri türü olan Interface ise tamamen diğer sınıflar için arayüz görevini taşır. Arayüzlerin bütün metotları ve özelliklerinin özet olarak bildirilmiş sınıflardan çok fazla farkı yoktur. Dolayısıyla arayüzlerdeki metotların ve özelliklerin gövdesi yazılamaz. Kısaca arayüzler, kendisini uygulayan sınıfların kesin olarak içerceği özellikleri ve metotları belirler.

 Arayüzler kişisel uygulamalarda pek fazla kullanılmaz ancak özellikle birkaç firmanın ya da programcının üzerinde çalıştığı projelerde ortak bir zemin oluşturabilmek için arayüzlerden faydalanılır.

Arayüz bildirimi:

Arayüzler, interface anahtar sözcüğü kullanılarak bildirilir. Bir arayüzde özellik, indeksleyici, metot, temsilci ve olay bildirimi yapılabilir. Arayüz isimleri geleneksel olarak I harfi ile başlar.

Arayüz bildirimi ile ilgili çeşitli kısıtlamalar vardır.

*Arayüzdeki elemanları statik olarak bildiremeyiz.
*Arayüzdeki eleman bildirimleri içsel olarak puplic oldukları için ayrıca bir elemanı erişim belirleyici ile bildirmek yanlıştır.
*Arayüzler herhangi bir üye değişken içeremez.
*Arayüzlerde yapıcı ve yıkıcı metotlar tanımlanamaz ya da bildirilemez.

Aşağıda iki metot, bir özellik ve bir indeksleyici bildirimi içeren arayüz tasarlayalım.

interface IArayuz
{
  int BirSonraki();
  void Sıfırla();
 
  int Deger
  {
   get;
   set;
  }
 
  int this[int indeks]
  {
  get;
  }
}

Bu arayüzü uygulayan bir sınıfta Arayüzde bulunan bütün elemanların uygulanması gerekir. Deger özelliğinin hem get hem de set blokları olmasına karşın indeksleyicinin sadece get bloğu vardır. Buna rağmen bu arayüzü uygulayacak sınıfta bildirilen indeksleyicinin hem get hem de set bloğu ya da sadece get bloğu olabilir, fakat sadece set bloğu olamaz.

Arayüzlerdeki hatalı kullanımları inceleyelim.

*Asağıdaki Arayüz bildiriminde metot puplic erişim belirleyicisi ile bildirildiği için geçersizdir.

  interface IArayuz
  {
    puplic void Metot();
  }


*Aşağıdaki Arayüz bildiriminde statik metot bildirimi yapıldığı için geçersizdir.

  interface IArayuz
  {
    static void Metot();
  }

 
*Aşağıdaki arayüz bildiriminde ise üye değişkenin bildirilmesi arayüzü geçersiz kılmıştır.

  interface IArayuz
  {
    int a;

    void Metot();

int Ozellik
{
get;
}
  }
 

Saturday, December 1, 2012

Özet (Abstract) Sınıflar (c#)


 Nesne tabanlı programlamada sınıf hiyerarşisi oluştuturken bazen hiyarerşinin en tepesinde bulunan sınıf türünden nesnelerin progmcılar için pek anlamı olmayabilir. Hiyerarşinin en tepesinde bulunan sınıfın kendisinden türetilecek olan alt sınıflar için ortak bir arayüz görevi görmesini isteyebiliriz. Örneğin Memeli sınıfında bulunan Konus() isimli metot çağrıldığında yapacağı iş belli değildir. Yani hangi türdenmemeli türünde konuşacağı belli değildir. Eğer Konus() Metodunu temel sınıfımızda tanımladan direkt kuş, kedi gibi alt sınıflarda tanımlarsak bu sefer Memeli sınıfından türeyecek sınıfların çok biçimliliği desteklememesi söz konusu olacaktır. Bunun için çözüm olarak, Memeli sınıfında Konus() metodu bildirilsin ancak herhangi bir işlevi özelliştirmesin, Memeli sınıfından türeyecek diğer sınıflar için bir arayüz görevi görsün. İşte bu amaçla oluşturulan metotlara ve sınıflara özet metot yada özet sınıf deriz.

   Özet sınıflar ya da özet metotlar abstract anahtar sözcüğü kullanılarak tanımlanır. Temel sınıf içerisinde bildirilen özet(abstract) metotların temel sınıf içerisinde gövdesi yoktur, sadece tanımlaması yapılır. Ancak bu temel sınıftan türeyen bütün sınıflar bu metodu override anahtar sözcüğü ile devre dışı bırakılmalıdır. Özet metotlar zaten sanal olarak görev yaptıkları için virtual anahtar sözcüğü ile sanal olarak tanımlamamıza gerek yoktur.

 Özet metotların Tanımlanması


 Özet sınıflar metot bildiriminin başına abstract anahtar sözcüğünün konulması ile bildirilir.

 abstract puplic void OzetMetot();
 /*Görüldüğü üzere metodumuzun tanımlanması " ; " ile sonlandırılmıştır. Yani metodumuzun gövdesi yoktur.*/

 abstract puplic void OzetMetot(){
 }

 şeklinde gövdesini boş bıraksakta bir metot tanımlamamız yasaklanmıştır.

 Özet sınıfların tanımlanması

  Özet sınıflarda abstract anahtar sözcüğü kullanılarak bildirilirler.  Bir özet sınıf türünden nesneler
 tanımlanamaz. Özet sınıflar ancak kendilerinden türeyen alt sınıflar için arayüz görevi görür.

 abstract class OzetSinif
 {
 }

 Özet sınıflar temel sınıfın tek başına anlamlı bir nesneyi ifade etmediği durumlarda kullanılır.
 Özet sınıfları kullanabilmemiz için özet sınıf türünden yeni sınıflar oluşturmalıyız.


 Her ne kadar Özet sınıftan nesler üretemesekte, özet sınıftan türeyen sınıf nesneleri üzerinden özet sınıfa
 ait yapıcılar kullanılarak özet sınıfın değişkenleri değiştirilebilir. Aşağıda Memeli sınıfından türeyen Kedi
 sınıfından nasıl nesnelerin oluşturulduğunu ve kullanıldığını göreceğiz.

 Using System;

 abstract class Memeli /*Özet sınıf tanımlandı. */
 {
     Puplic double en;
Puplic double boy;

puplic Memeli(double en, double boy)
{
this.en=en;
this.boy=boy;
}
 }

 class Kedi : Memeli
 {
    String Turu;
    puplic Kedi(string turu, double en, double boy) :  base(en,boy)
    {
      this.Turu=turu;
    }
 }

 class MainMetodu
 {
    static void Main()
{
 Kedi kedi = new Kedi("van", 5, 15);
 console.writeline("kedinin eni: "+ kedi.en);
 console.writeline("keninin boyu: " + kedi.boy);


Temel sınıfta oluşturulan abstract metotlar türeyen sınıflarda devre dışı bırakılmalır. Eğer abstract metot
devre dışı bırakılmaz ise derleyici hata verecektir.
Örneğin;

 Using System;

 abstract class Memeli /*Özet sınıf tanımlandı. */
 {
     Puplic double en;
Puplic double boy;

puplic Memeli(double en, double boy)
{
this.en=en;
this.boy=boy;
}

abstract puplic void konus(); /* özet metodumuzu tanımladık. Özet metodumuz Memeli sınıfından türetilecek olan alt sınıflar tarafından devre dışı bırakılmalıdır.*/
 }

 class Kedi : Memeli
 {
    String Turu;
    puplic Kedi(string turu, double en, double boy) :  base(en,boy)
    {
      this.Turu=turu;
    }
 }
 Bu programda derleyici " Kedi türediği sınıfın özet metodu olan Memeli.Konus() metodunu devre dışı
 bırakmamıştır" hatası verecektir. Hatayı düzetlmek için Özet sınıftan türetilen Kedi sınıfı içerisinde
 Özet metot olan Konus Metodunu  Override void Konus()  Tanımlamasıyla devre dışı bırakılmalıdır.


 Metotlar ve sınıflar gibi özellikler de özet olarak bildirilebilir. get ve set bloğu olan bir özet özellik
 aşağıdaki gibi tanımlanır.

 abstract class OzetOzellik
 {
 abstract puplic int A
 {
   get;
   set;
 }
 }

 Ozet ozellik sınıfından türeyen bir sınıf A özelliğini hem get hem de set blokları ile birlikte uygulamak
 zorundadır. Eğer temel sınıfta get yada set bloklarından herhangi biri bildirilmiş olsaydı türeyen sınıfta
 sadece ilgili blok yazdırılırdı.

 abstact class Temel
 {
   abstract puplic int A
   {
    get;
set;
}
  }

 class Tureyen : Temel
 {
 int a;

  puplic override int A
  {
  get{
   return a;
   }
 }

 Özet sınıflar ve metotlar ile genel özellikler

 1.Özet sınıflar türünden nesneler tanımlanamaz.

 2.Özet sınıflar, özet metotlar içerebilirler. Özet metotlar ancak özet sınıfların içinde bildirilebilir.

 3.Özet sınıflar ealed anahtar sözcüğü ile işaretlenemezler.

 4.Özet bir sınıftan türeyen sınıflar temel sınıftaki bütün özet metotları uygulamalıdır. Yani metodun gerçek
 gövdesi türeyen sınıflarda yazılmalıdır.

 5.Bir özet metot ancak bir özet içinde bildirilebilir.

 6.Bütün özet sınıflar içsel olarak sanaldır. bu yüzden virtual olduklarını belirtmeye gerek yoktur.

 7.Özet metotlar türeyen sınıfta mutlaka bildirilmelidir.

 8.Statik metotlar özet olarak bildirilemez.

 9.Sınıflarda özet özellikler de bildirilebilir, türeyen sınıflarda bu özet özellikler override anahtar
 sözcüğü ile tekrar bildirilmelidir.

 10.Bir özet sınıf içinde özet olmayan metotlar da bildirilebilinir. Ancak bir sınıf içinde özet metot bildirilmiş
 ise o sınıf özet olarak tanımlanmalıdır.

Friday, November 2, 2012

Çok Biçimlilik(Polymorphism) (c#)


Tek bir metot ile birçok sınıfa ait farklı versiyondaki metotlar çağrılabilmektedir. Üstelik bu işlem aynı
nesne üzerinden olmaktadır. Bir nesnenin bu şekilde çoklu özellik göstermesine çok çeşitlilik(polymorphism)
denilmektedir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Polymorphism
{
    class Sekil
    {
        public double Boy;
        public double En;

        public Sekil(double boy, double en)  /* kurulurken boy ve en değerlerini alan constructor yazdık */
        {
            this.Boy = boy; /* base sınıfta sadece boş constructor olduğunda kullanılması yaygındır.*/
            this.En = en;
        }
        public Sekil()
        {
        }
        virtual public double Alan() /*sanal alan metodu yazdık. türeyen sınıfta Alan() metodu varsa buradaki 
                                                  ezilecektir.*/
        {
            return 0;
        }
    }

    class Dortgen : Sekil /* sekil sınıfından dortgen sınıfını türettik*/
    {
        public Dortgen(int boy, int en)
            : base(/*boy,en*/)       /* alınan değerleri türetilen sınıftaki   değişkenlere gönderiyor.
                                                 Base.Boy tanımlamamıza gerek olmuyor. */
     /*eger base sınıfta (boy,en) constructorı yoksa bunu kullanamayız.*/
         
        {
            base.Boy = boy; /* base sınıfta sadece boş constructor olduğunda kullanılması yaygındır.*/
            base.En = en;
        }

        public override double Alan()  /* eger kurulan sınıf dortgen olursa sekil sınıfındaki Alan() metodu yerine 
                                                       buradaki Alan() çağırılacak*/
        {
            return En * Boy;
        }

    }
    class Ucgen : Sekil
    {
        public Ucgen(int boy, int en)
            : base(boy, en) /* eger base sınıfta (boy,en) constructorı yoksa bunu kullanamayız.*/
        {
        }

        public override double Alan()  /* eger kurulan sınıf dortgen olursa sekil sınıfındaki Alan() metodu yerine 
                                                      buradaki Alan() çağırılacak*/
        {
            return En * Boy / 2;
        }
    }

    class MainMetodu
    {
        public static void AlanBul(Sekil sekil)
        {
            Console.WriteLine("seklin alanı: " + sekil.Alan());
        }
        static void Main()
        {
            Ucgen ucgen = new Ucgen(10, 50);
            AlanBul(ucgen);

            Dortgen dortgen = new Dortgen(10, 50);
            AlanBul(dortgen);

            Sekil sekil = new Sekil(10, 50);
            AlanBul(sekil);

            Console.ReadLine();
        }
       
    }
}


ekran çıktısı:

250
500
0
   şeklinde olacaktır.
 
   Gördüğümüz gibi statik AlanBul() metodu Sekil türünden bir nesne beklemesine rağmen Sekil Türünden
   türeyen Ucgen ve Dortgen nesnelerini de kabul etmektedir. Üstelik bu Ucgen Ve Dortgen nesneleri metodun
   parametresi olan Sekil nesinesine aktarilmasına rağmen Ucgen ve Dortgen sınıflarındaki Alan() metotları
   çağrılabilmiştir. Bunu sağlayan da süphesiz Alan() metodunun sanal olarak bildirilmesi ve Türeyen
   sınıflarda bu metodunun devre dışı bırakılmasıdır.
 
   Türeyen sınıflar, temel sınıflardaki sanal metotları devre dışı bırakmak zorunda değildir. eğer türeyen
   sınıfta ana sınıftaki sanal metodu ezecek bir sınıf tanımlanmadıysa türeyen sınıf için de ana sınıftaki
   sanal metot geçerli olur. Aşağıda örneklendirmek gerekirse;
 
   class Dortgen : Sekil
   {
     puplic Dortgen(int boy, int en):base (boy,en)
{
}
}
 Dortgen metodumuz bu şekilde olsaydı
 Dortgen dortgen= new Dortgen(10,50);

 dortgen.Alan()  için ana sınıftaki yani Sekil sınıfındaki virtual tanımlanan Alan() metodu geçerli
 olacaktı.

 Hiyerarşik sınıf yapılarında bu kural geçerlidir. Hiyerarşik yapılardaki sınıflarda yukarıdaki gibi
 bir kullanım söz konusu olursa en alttan en üste doğru Alan() metodunun ilk devre dışı bırakıldığı
 sınıfa ait metot çağırılır.


 Çok çeşitlilik ve metotların devre dışı bırakılması ile ilgili öğrendiklerimizi pekiştirmek gerekirse;


 1. Eğer metot sanal olarak bildirilmemişse, derleyici nesnelerin tür bilgisinden faydalanarak derleme
 zamanında hangi metodun çağrılcağını bilir.

 2. Eğer metot sanal olarak bildirilmiş ise, derleyici derleme aşamasında ürettiği kod ile çalışma
 zamanında referansın türüne göre ilgili sınıfın devre dışı bırakılmış metodunu çağırır.

 3. Hangi metodun çağıracağının çalışma zamanında belirlenmesine geç bağlama(late binding)
          denilmektedir.

 4. Sanal metot bildirmek için virtual anahtar sözcüğü kullanılır.

 5. Türeyen sınıfta, temel sınıftaki sanal metodu devre dışı bırakmak için override anahtar sözcüğü
 kullanılır.

 6. Türeyen sınıfta devre dışı bırakılan metotların temel sınıftaki sanal metotların ismi aynı olamk
 zorundadır.

 7. Türeyen sınıfta devre dışı bırakılan metotların parametrik yapısı temel sınıftaki parametrik yapısı
 ile aynı olmak zorundadır.

 8. Statik metotlar sanal olarak bildirilemez.

 9. Türeyen sınıflar, temel sınıftaki sanal metotları devre dışı bırakmak zorunda değildir. Bu durumda
 temel sınıf referansı üzerinden temel sınıfa ait metot çağırılır.

Wednesday, October 31, 2012

Sanal Metotlar Örneği (c#)


Temel Ev Sınıfı:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

   /*kalitimda türetilen classların namespaceleri aynı olması tek bir referans üzerinden erişmemiz için kolaylık 
      sağlar.*/
namespace emlakci
{
    public class Ev
    {
        private int odasayisi;
        public int Odasayisi
        {
            get { return odasayisi; }
            set { odasayisi = value; }
        }
        private int katno;

        public int Katno
        {
            get { return katno; }
            set { katno = value; }
        }
        private int alan;

        public int Alan
        {
            get { return alan; }
            set { alan = value; }
        }
        private string semt;

        public string Semt
        {
            get { return semt; }
            set { semt = value; }
        }

        public Ev()
        {
        }
        public Ev(int odasayisi, int katno, string semt, int alan)
        {
            this.odasayisi = odasayisi;
            this.katno = katno;
            this.semt = semt;
            this.alan = alan;
        }

        /* virtual sanal anlamına gelir. virtual tanımlanan metotlar override ile tanımlanan metotlar tarafından 
          ezilebilir.*/
        public virtual string EvGoruntule()
        {
            return string.Format(" Odasayisi: {0} Katno: {1} Alan: {2} Semt: {3}", odasayisi, katno, alan, semt);
        }
    }
}


Türeyen Satılık Ev Sınıfı:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*kalitimda türetilen classların namespaceleri aynı olması tek bir referans üzerinden erişmemiz için kolaylık sağlar.*/
namespace emlakci
{
    public class satilikev : Ev
    {
        private int fiyat;

        public int Fiyat
        {
            get { return fiyat; }
            set { fiyat = value; }
        }
        private int kapora;

        public int Kapora
        {
            get { return kapora; }
            set { kapora = value; }
        }

        public satilikev(int odasayisi, int katno, int alan, string semt, int fiyat, int kapora) : base()
        {
            base.Alan = alan;
            base.Katno = katno;
            base.Semt = semt;
            base.Odasayisi = odasayisi;
            this.fiyat = fiyat;
            this.kapora = kapora;
        }

        /*override ezmek anlamına gelir. Base sınıfındaki virual tanımlanmış metodun yerine önceliği alır. Artık
          virtual metot yerine aktif
         * olan sınıf override sınıfı olur. base sınıfındaki virtual metodu yerine öncelikli olarak override sınıflarla 
           işlem yapılır. eğer 
         * override sınıfı bulunmaz ise virtual sınıf ile işleme devam edilir. */
        /* override tanımladığımız metot türetilen sınıftaki virtual metodu yerine çağrışır. bir anlamda virtual 
           metodunu ezer. */

        public override string EvGoruntule()
        {
            return base.EvGoruntule() + " Fiyat: " + fiyat +  " Kapora: " + kapora;
        }
    }
}

Türetilen Kiralık Ev Sınıfı:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*kalitimda türetilen classların namespaceleri aynı olması tek bir referans üzerinden erişmemiz için kolaylık sağlar.*/
namespace emlakci
{
    public class kiralikev:Ev
    {
        public kiralikev()
        {
        }

        public kiralikev(int odasayisi, int katno, int alan, string semt, double kira) : base(/*aşağıdaki tanımları 
                                                                                                                              burada yapabilirdik.*/)
        {
           /*yukarıdaki boş base constructori dolu olsaydı tekrardan base ile ataması yapmamıza gerek 
             kalmayacaktı. */
           base.Odasayisi = odasayisi;
           base.Katno = katno;
           base.Alan = alan;
           base.Semt = semt;
           this.kira = kira;
         
        }

        public double kira;
        public double depozito;

        /*override ezmek anlamına gelir. Base sınıfındaki virual tanımlanmış metodun yerine önceliği alır. Artık 
         virtual metot yerine aktif
         * olan sınıf override sınıfı olur. base sınıfındaki virtual metodu yerine öncelikli olarak override sınıflarla 
            işlem yapılır. eğer 
         * override sınıfı bulunmaz ise virtual sınıf ile işleme devam edilir. */
        /* override tanımladığımız metot türetilen sınıftaki virtual metodu yerine çağrışır. bir anlamda virtual 
         metodunu ezer. */
        public override string EvGoruntule()
        {
            return base.EvGoruntule() + " Kira " + kira + " Depozito: " + depozito;
        }
    }
}




Main Sınıfı:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using emlakci;

//Not: base sınıf üzerinden kalıtım sınıflarına erişebilme:

namespace kalitimsinifi
{
    class Program
    {
        static void Main(string[] args)
        {
            /*kalitim tüm sınıfları base sınıf üzerinden kullanabilme imkanı verir.
            fakat o sınıflara has alanı görmek için gerçek tipine cast etmemiz gereklidir. */

            Ev ev1 = new kiralikev(1, 1, 1, "1", 1);
            Ev ev2 = new satilikev(2, 2, 2, "2", 2, 2);
            Ev ev3 = new kiralikev(3, 3, 3, "3", 3);
            Ev ev4 = new satilikev(4, 4, 4, "4", 4, 4);
            kiralikev ev5 = new kiralikev(5, 5, 5, "5", 5);
            satilikev ev6 = new satilikev(6, 6, 6, "6", 6, 6);

            Ev[] evler = new Ev[6];
            evler[0] = ev1;
            evler[1] = ev2;
            evler[2] = ev3;
            evler[3] = ev4;
            evler[4] = ev5;
            evler[5] = ev6;
         
            for (int i = 0; i < evler.Length; i++)
            {
                Console.WriteLine(evler[i].EvGoruntule());

                if (evler[i] is kiralikev)
                {
                   /* kiralikev sinifindan bir nesne tanımlıyoruz ve bu nesneye evler[i] nesnesini (kiralikev) 
                    operatörüyle casting edip atıyoruz.)*/

                   kiralikev ke = (kiralikev)evler[i];

                   /* NOT: (evler[i] as kiralikev).depozito deyimi casting ile aynı görevi görür. */
                   Console.WriteLine(" depozito: "+ ke.depozito);
                }
            }

            Console.ReadLine();
        }

    }
}

Sanal Metotlar (c#)


Şu ana kadar bir nesne üzerinden çağırdığımız metotların tamamı derleme zamanında belirgindi. Yani derleme
aşamasında hangi nesne üzerinden hangi metotların çaığrabileceği belliydi. Sanal metotlar yardımıyla çalışma
zamanında metot seçme işinin nasıl olduğunu inceleyeceğiz.

Sanal metotlar temel sınıflar içinde bildirilmiş ve türeyen sınıflar içinde de tekrar bildirilen metotlardır.
Sanal metotlar nesne yönelimli programlama tekniğindeki çok biçimliliği(polimorphism) uygulayan yapılardır.
Temel sınıfta bir sanal metot bildirildiğinde bu temel sınıflar, temel sınıftaki sanal metodu devre dışı bırakarak
kendi metot gövdelerini oluşturabilirler.

Sanal metotlar sayesinde Temel sınıf türünden bir referansa türeyen sınıf referansları aktarıldığında, temel
sınıf referansı üzerinden kendisine aktarılan türeyen sınıfın sanal metodu çağrılabilir. Eğer türeyen sınıf
sanal metodu devre dışı bırakmamış ise temel sınıftaki sanal metot çağrılır. Çağrılan metodun hangi türe ait
olduğu çalışma zamanında belirlenir. Metotların bu şekilde çalışma zamanında belirlenmesine geç bağlama
(late binding) denilmektedir.

Sanal metotlar virtual anahtar sözcüğü kullanılarak bildirilir. Bu anahtar sözcük, metot bildirimin başına
eklenirse soyut metotlar bildirilmiş olur. Türeyen sınıfta, temel sınıftaki soyut netotları devre dışı
bırakmak için ise override anahtar sözcüğü kullanılır.


Sanal metotların etkin kullanılığı bir örnek;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SanalMetotlar
{
    class Memeli
    {
        public double Boy;
        public double Agirlik;

        public Memeli(double boy, double agirlik)
        {
            this.Boy = boy;
            this.Agirlik = agirlik;
        }

        virtual public void Konus()  /* Türetilen sınıflar ile işlem yapılacağı zaman, Konus() metodu 
                                    türetilen sınıfta override anahtar sözcüğü ile tanımlanmış ise
                                                   Türetilen sınıftaki metot çağıralacak. */
        {
            Console.WriteLine("ben konusamam");
        }
    }

    class kedi : Memeli
    {
        public string Turu;
        public kedi(string turu, int boy, int agirlik)
            : base(boy, agirlik)
        {
            this.Turu = turu;
        }

        override public void Konus()  /* Kedi sınıfı ile işlem yapılacağı zaman Base sınıftaki virtual ile
                                tanımlanan Konus() metodu yerine buradaki konus() metodu çağıralacak.*/
                               
        {
            Console.WriteLine("Ben bir kediyim");
        }
    }

    class koyun : Memeli
    {
        public string Turu;
        public koyun(string turu, int boy, int agirlik)   : base(boy, agirlik)  /* alınan değerleri türetilen sınıftaki  
                                                          değişkenlere gönderiyor. Base.Boy  tanımlamamıza gerek kalmıyor */
        {
            this.Turu = turu;
        }

        override public void Konus() /* Koyun sınıfı ile işlem yapılacağı zaman Base sınıftaki virtual ile
                                tanımlanan Konus() metodu yerine buraki konus() metodu çağıralacak.*/
        {
            Console.WriteLine("Ben bir koyunum");
        }
    }

    class MainMetodu
    {
        static void Main()
        {
            Memeli memeli1 = new Memeli(20, 30);
            kedi kedi1 = new kedi("Van", 10, 15);
            koyun koyun1 = new koyun("keçiören", 60, 80);

            memeli1.Konus();


            memeli1 = kedi1;
            memeli1.Konus();


            memeli1 = koyun1;
            memeli1.Konus();

           

            Console.ReadLine();

        }
    }
}

ekran çıktısı;

ben konusamam
ben kediyim
ben koyunum  

 Şeklinde olacaktır. Kedi ve Koyun nesneleri ait referans aktarılmasına rağmen çalışma zamanında bu Memeli
 referansı üzerinden Konus() metodunu çağırdığımızda Memeli sınıfındaki Konus() metodu yerine kendisine
 atanan sınıflara ait Konus() metotları çağrılmıştır.

 Sanal metotlar sayesinde temel sınıf referanslarına türeyen sınıf referansları atandığında, temel sınıf
 referansı üzerinden türeyen sınıfa ait metotları çağırabilmekteyiz. Bu yöntemle sadece temel sınıfta sanal
 olarak bildirilmiş metotların türeyen sınıfta devre dışı bırakılmış olan metotlara erişilebilir.

Sunday, October 14, 2012

Is ve As Operatörleri (c#)


As  Operatörü

as operatörü uygun türler arasındaki dönüşümü sağlar. Kullanımı aşağıdaki biçimdedir.

<referans tipi üretitilecek ifade>   as   <referans türü>

as operatörü kullanımı fazla yaygın değildir. as operatörün ürettiği değer referans türündendir, eğer dönüşüm işlemi
başarızsa null değer üretilir. Örneğin object türünden olan bir nesne string türüne aşağıdaki şekilde dönüştürülür.

Using System;

class Operatorler
{
   static void main()
   {
      object i = "50";
      string s = i as string;
      console.writeline(s);
   }
}


Is Operatörü

is operatörü çalışma zamanında bir nesnesinin türünün operand ile verilen türe uyumlu olup olmadığını kontrol eder.
Kullanımı aşağıdaki gibidir.

<ifade> is <tür>

is operatörü de as operatörü gibi pek fazla kullanılmamaktadır. Ancak yine de dilin olanaklarından haberdar olmak önemlidir.
is operatörünün ürettiği değer true ya da false değeridir. Eğer operandlardaki türler uyumlu ise true, değilse false
değeri üretilir.

<ifade> is <tür> ifadesinin her zaman true ya da her zaman false üretmesi durumunda derleyici hata bir uyarı verecektir.
ancak bu derleme işlemine engel değildir.

Aşağıda ki programı derlediğimizde derleyicinin verdiği uyarının ekran görüntüsü şöyledir:

using Operatorler
{
  static void main()
  {
    int i = 50;
    bool b1 = is int;
    bool b2 = is double;
    bool b3 = is object;
 
   console.writeline(b1);
   console.writeline(b2);
   console.writeline(b3);

  }
}

  Verilen ifade her zaman ('int') türünü sağlar.
  Verilen ifade hiçbir zaman ('double') türünü sağlamaz.
  Verilen ifade her zaman ('object') türünü sağlar.

  Yukaridaki programı çalıştırdığımızda ise aşağıdaki ekran görüntüsünü elde ederiz.
  True
  False
  True

Friday, October 5, 2012

Kalıtım Örneği (c#)


Bu örneğimizde temel bir Ev sınıfı oluşturacağız. Oluşturduğumuz temel ev sınıfında tüm evler için kullanılabilinir özellikler olan kat numarası, oda sayısı, alanı, semti gibi özellikler olacak. Temel Ev sınıfından bir KiralıkEv sınıfı türeteceğiz ve bu sınıfımızda sadece kiralik evler için geçerli olan depozito ve kira özelliklerini ekleyeceğiz. Ardından Main metodunun bulunduğu sınıfta nesne örneklerimizi oluşturacağız.


Temel Ev Sınıfı:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace evsinifi
{
    public class Ev
    {
        private int odasayisi;

        public int Odasayisi
        {
            get { return odasayisi; }
            set { odasayisi = value; }
        }
        private int katno;

        public int Katno
        {
            get { return katno; }
            set { katno = value; }
        }
        private int alan;

        public int Alan
        {
            get { return alan; }
            set { alan = value; }
        }
        private string semt;

        public string Semt
        {
            get { return semt; }
            set { semt = value; }
        }

   

        public string EvGoruntule()
        {
            return string.Format(" Odasayisi: {0} Katno: {1} Alan: {2} Semt: {3}", odasayisi, katno, alan, semt);
        }
    }
}

Ev sınıfından türetilen KiralıkEv sınıfı:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/*kalitimda türetilen classların namespaceleri aynı olması tek bir referans üzerinden erişmemiz için kolaylık sağlar.*/

namespace kiraliksinifi
{
    public class kiralikev:Ev
    {
        public kiralikev()
        {
        }

        public kiralikev(int odasayisi, int katno, int alan, string semt, double kira) : base(/*boş yerine dolu olabilirdi*/)
        {
           /*yukarıdaki boş base constructori dolu olsaydı tekrardan base ile ataması yapmamıza gerek kalmayacaktı. */
           base.Odasayisi = odasayisi;
           base.Katno = katno;
           base.Alan = alan;
           base.Semt = semt;
           this.kira = kira;
           
        }

        public double kira;
        public double depozito;

        public string EvGoruntule()
        {
            return string.Format(" Odasayisi: {0}, Katno: {1}, Alan: {2}, Semt: {3}, kira: {4}", Odasayisi, Katno, Alan, Semt, kira);
        }
    }
}

Main metodunun bulunduğu ana sınıf:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using evsinifi;
using kiraliksinifi;


namespace Kalitim
{
    class Program
    {
        static void Main(string[] args)
        {
            kiralikev ev1 = new kiralikev();
            ev1.Alan = 120;
            ev1.Katno = 3;
            ev1.Odasayisi = 4;
            ev1.Semt = "bebek";
            ev1.kira = 550;

            Ev ev2 = new Ev();
            ev2.Alan = 120;
            ev2.Katno = 3;
            ev2.Odasayisi = 4;
            ev2.Semt = "Etiler";

            kiralikev ev3 = new kiralikev(3,7,120,"besiktas",430);

            Console.WriteLine(ev1.EvGoruntule());
            Console.WriteLine(ev2.EvGoruntule());
            Console.WriteLine(ev3.EvGoruntule());

           
            Console.ReadLine();
        }
    }
}

Kalıtım (c#)

Temel bir Memeli sınıfı tasarlayacağız. Her memeli hayvan da  bulunan özellikler boy, ağırlık gibi fiziksel özellikler
olabilir. Daha sonra Kedi sınıfını tasarlayacağız. Ancak Kedi sınıfı Memeli sınıfından türeteceğiz. Yani Memeli sınıfının
tüm özelliklerini Kedi sınıfına aktaracağız. Memeli sınıfında boy ve ağırlık bilgilerini gösteren OzelliklerGoster()
isimli bir metot olacak. Kedi sınıfında da hayvanın kedi olduğunu gösteren string türünden bir özellik olacak.
Ayrıca Kedi sınıfında kedinin türünü yazdıracak bir de metot olmalıdır.

Türetme işlemi aşağıdaki gibi yapılır.

class Kedi: Memeli
{


}

burada kedi sınıfından türemiş sınıf(derived class) Memeli ise temel sınıf (base class) olarak adlandırılır. Şimdi bu sınıfların nasıl yazıldığına bakalım.

using system;

class Memeli
{
  puplic double Boy;
  puplic double Agirlik;

  puplic void OzellikGoster()
  {
    console.WriteLine("Boy = " + Boy);
    console.WriteLİne("Ağırlık = " Agirlik);
  }

}


class Kedi:Memeli
{
  puplic string Tur;

  puplic void TurGoster();
  {
   console.writeline("Turu: " + Tur);
  }
}

Class MainMetodu
{
  Private void Main(String [] Args)
  {
   Kedi kedi1 = new Kedi();

   kedi1.Boy= 15;
   kedi1.Agırlık = 4;
   kedi1.Tur = "Van";
 
   kedi1.OzellikGoster();
   kedi1.TurGoster();

   Kedi kedi2 = new Kedi();
   kedi2.Boy= 19;
   kedi2.Agırlık = 8;
   kedi2.Tur = "kara";
 
   kedi2.OzellikGoster();
   kedi2.TurGoster();

   Console.ReadLine();
  }
}

Bu programın ekran çıktısı;

Boy = 15
Agırlık = 4
Turu = Van

Boy =  19
Agırlık = 8
Turu = Kara

şeklinde olacaktır.


Gördüğünüz üzere Kedi sınıfı üzerinden Memeli sınıfına ait bütün özelliklere ve metotlara erişebiliyoruz.
Bunu sağlayan,

class Kedi : Memeli
{
}
satırıdır.

Ancak yazdığımız programda;

Memeli memeli = new Memeli();
memeli.TurGoster();

şeklinde Türeyen sınıftaki metoda erişmemiz mümkün değildir.

Programı derlemeye çalıştığımızda hata mesajı alırız; çünkü memeli nesnesi üzerinden TurGoster() metoduna ulaşamayız.
Yani temel sınıf olarak Memeli sınıfının kendisinden türeyen Kedi sınıfındaki üye elemanlardan haberi yoktur.
Ancak tersi doğru değildir.



Wednesday, October 3, 2012

Singleton Tasarım Örneği (C#)


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Evler
{
    public class Ev
    {
        /*static elemanlar içerisinde static elemanlar çağrılabileceği için static tanımladık. */
       static Ev instance;


       /* dışardan bir müdahale olmaması için private tanımlanan ev türünden instance değerine belirleyici yazmalıyız.*/
        public static Ev Instance
        {
            get
            {
                /* ev sınıfının nesne örneğini geri döndürmek için; */
                return Ev.instance;
            }
        }

        /* yeni sınıf oluşturulmaması için dışardan ulaşılmamak üzere private tanımlanmalı. */
        private Ev()
        {
         

        }

        public void deneme(double alan2)
        {
            this.Alan=alan2;
        }

      /* static constructorlar parametre almazlar ve private olarak tanımlanırlar. */
      /* ev sınıfından nesne kurulmadan çalıştırılması gerektiği için static tanımladık. diğer türlü sınıfı kurmadan
       constructor çağırmamız mümkün olmayacak ve new anahtar sözcüğünü bir kereyle sınırlandırma şansımız 
       olmayacaktı. */
        static Ev()
        {
            /* instance static olarak tanımlandığı için buradaki static metot tarafından çağrılabiliyor. */
            /* instance değişkeni ile Ev sınıfı kurulduğu anda bellekte bir kereye mahsus olmak üzere new anahtar 
             sözcüğü ile Ev sınıfı için yer oluşturuluyor. daha sonra ev sınıfından üretilen nesneler aynı özellikleri 
             taşıyacaktır. */
            instance = new Ev();
        }

        private static int katno;
        private int odasayisi;
        private double alan;
        private string semt;

        public int Katno
        {
            get
            {
                return katno;
            }

            set
            {
                katno = value;
            }
        }

        public int Odasayisi
        {
            get
            {
                return odasayisi;
            }

            set
            {
                odasayisi = value;
            }
        }

        public double Alan
        {
            get
            {
                return alan;
            }

            set
            {
                alan = value;
            }
        }

        public string Semt
        {
            get
            {
                return semt;
            }

            set
            {
                semt = value;
            }
        }

        public String EvBilgileriniGetir()
        {
            return string.Format(" katno: {0} \n odasayisi: {1} \n alan: {2} \n semt: {3}", katno, odasayisi, alan, semt);
        }

    }


ana program;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Evler;

namespace ConsoleApplication12
{
    class Program
    {
        static void Main(string[] args)
        {
            /* ev ilk kurulduğu anda instance sözcüğü new anahtar sözcüğünü işaret edicek bellekte bir kereliğine
             sınıf için yer açılacak. ardından kurulan her nesne örneği aynı referansı temsil edecektir. */
            Ev ev1 = Ev.Instance;

            ev1.Katno = 3;
            ev1.Odasayisi = 2;
            ev1.Semt = "besiktas";

            Ev ev2 = Ev.Instance();
            ev2.deneme(2);
            ev2.Katno = 11;

            /* ev1 veya ev2 yazmamız bir şeyi değiştirmicektir üzerinde çalıştığımız nesne aynıdır. */
            Console.WriteLine(ev1.EvBilgileriniGetir());

            Console.ReadLine();
        }
    }
}

}

Singleton (Tek) Nesneler (C#)


Singleton (Tek) Nesneler

singleton deseni bir programın yaşam süresince belirli olan bir nesneden sadece bir örneğin(instance) olmasını garantiler.
Aynı zamanda bu desen, yaratılan tek nesneye ilgili sınıfın dışından global düzeyde mutlaka erişilmesini hedefler.

Yeni bir nesne oluşturmak için new anahtar sözcüğünün temsil ettiği yapıcı metoduna dışarıdan erişimin olması gerekir.
Yani yapıcı metodun puplic olarak bildirilmiş olması gerekir. Ancak singleton desenine göre belirli bir anda sadece bir
nesne olabileceği için new anahtar sözcüğünün kullanımının yasaklanması gerekir yani yapıcı metotodun protected ya da private
olarak bildirilmesi gerekir.

Eğer bir metodun varsayılan yapıcı metodu puplic olarak bildirilmemiş ise ilgili sınıf türünden herhangi bir nesnenin sınıfın
dışında tanımlanması mümkün değildir.

Bizim istediğimiz yalnızca bir sınıfın yaratılması olduğuna göre bunu ancak statik üye elemanlar ile yapabiliriz.

1. yöntem:

Puplic class Ev
{

   /*static elemanlar içerisinde static elemanlar çağrılabileceği için static tanımladık. */
   private static Ev ornek;
 
   /* dışardan bir müdahale olmaması için private tanımlanan ev türünden instance değerine belirleyici yazmalıyız.*/
   Puplic Static Ev Ornek
   {
     get
     {
      /* ev sınıfının nesne örneğini geri döndürmek için; */   
       return Ev.ornek;
     }
   }

  /* yeni sınıf oluşturulmaması için dışardan ulaşılmamak üzere private tanımlanmalı. */
  Private Ev()
  {

  }


   /* static constructorlar parametre almazlar ve private olarak tanımlanırlar. */
   /* ev sınıfından nesne kurulmadan çalıştırılması gerektiği için static tanımladık. diğer türlü sınıfı kurmadan constructorı
    * çağırmamız mümkün olmucak ve new anahtar sözcüğünü bir kereyle sınırlandırma şansımız olmucaktı. */
   Static Ev()
  {

       /* instance static olarak tanımlandığı için buradaki static metot tarafından çağrılabiliyor. */
       /* instance değişkeni ile Ev sınıfı kurulduğu anda bellekte bir kereye mahsus olmak üzere new anahtar sözcüğü ile
        * Ev sınıfı için yer oluşturuluyor. daha sonra ev sınıfından üretilen nesneler aynı özellikleri taşıyacaktır. */
     ornek= New Ev();
  }


2.yöntem:

Puplic class Ev
{
  private static Ev ornek;

  Private Ev()
  {
  }

 /* nesne üzerinden erişilmesine gerek kalmadan direkt sınıf ile erişilmesi için statik olmak zorunda */
 
  Puplic static Ev Ornek()
  {
   
      if ( nesne == null)
          nesne = new Ev();
   
     return nesne;
    }

 }
    Gördüğümüz üzere nesne ile ilk olarak sınıf belleğe yüklediğinde değilde o nesneyi ilk defa kullanmak istediğimizde
   yaratılıyor. ilgili nesneyi her istediğimizde yeni bir nesnenin yaratılmaması içinde
   if(nesne == null)
   şeklinde bir koşul yazdığımıza dikkat edin.
 
   sınıf yaratmak için Ev evim = Ev.Ornek();

Monday, September 24, 2012

Constructors ve statik metot örneği (c#)


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Evler
{
    public class Ev
    {

        /*constructor*/
        /* başta kendiliğinden kuruluyor */
        public Ev()
        {

        }

        /* nesnenin tüm özellikleri sınıf kurulurken atanıyor*/
        public Ev(int katno, int odasayisi, double alan, string semt)
        {
            this.katno = katno;
            this.odasayisi = odasayisi;
            this.alan = alan;
            this.semt = semt;
        }

        /* sadece semti belli olan nesnelerin kurulumunde tercih edilir */
        public Ev(String semt)
        {
            this.semt = semt;
        }

        /* Static ile oluşturulan constructor, sınıf program içersinde ilk kurulduğu anda bir kereye mahsus oluşturulur. */
        /* Static ile constructor oluşturma kurulan sınıf içersinde dosya yazdırılacağı zaman ilk başta dosyanın oluşturulması gibi
         * adımlarda işimizi kolaylaştırır. */
       
        static Ev()
        {
            Console.WriteLine("ilk ev oluşturuldu");
        }

        /*fields */
        private int katno;
        private int odasayisi;
        private double alan;
        private string semt;

        /* Protected erişim belirleyicisi*/
        public int Katno
        {
            get
            {
                return katno;
            }

            set
            {
                katno = value;
            }
        }

        public int Odasayisi
        {
            get
            {
                return odasayisi;
            }

            set
            {
                odasayisi = value;
            }
        }

        public double Alan
        {
            get
            {
                return alan;
            }

            set
            {
                alan = value;
            }
        }

        public string Semt
        {
            get
            {
                return semt;
            }

            set
            {
                semt = value;
            }
        }


        public String EvBilgileriniGetir()
        {
            return string.Format(" katno: {0} \n odasayisi: {1} \n alan: {2} \n semt: {3}", katno, odasayisi, alan, semt);
        }

        /*Const */
        const double katsayi = 3.44;

        /*Static */
        /*Nesne üzerinden erişilmesine gerek olmayan koşullarda kullanılır, direkt sınıf üzerinden erişilir. */
        public static double KatsayiGonder(double alan)
        {
            return alan * katsayi;
        }
    }
}

Statik Üye Elemanlar (c#)


Statik Üye Elemanlar

c# dilindeki tüm metotlara sınıflar üzerinden erişiriz. Çoğu durumda da erişim için bu sınıflardan nesneler oluştururuz.
Ancak bazı durumlarda metotları kullanmak için nesne oluşturmamız gereksiz olabilir. Bu durumda statik metotlar tanımlanır.
Statik metotlar olabiliceği gibi statik üye değişkenler ve statik yapıcı metotlarda olabilir. Bir üye elemanının statik
olduğunu bidirmek için bildirimden önce static anahtar sözcüğü eklenir.

Statik elemanlar bir sınıfın global düzeydeki elemanlarıdır. Yani statik üyeleri kullanmak için herhangi bir nesne
 tanımlamıza gerek yoktur. Şimdi sırasıyla üye elemanları inceleyelim.



STATİK METOTLAR



Metotlar konusunda Math sınıfının çeşitli metotlarını görmüştük Bu metotları herhangi bir nesne oluşturmadan kullanabildik.
Örneğin bir sayının karekökünü almak için
Math.sqrt(sayi);
ifadesini kullanmamız yeterliydi. Karekök alma işlemi genel bir işlem olduğu için bu tür işleri yapmak için nesne tanımlamamız
çok saçma olurdu. Neyse ki c# dilini tasarlayanlar bunu düşünmüşler. Statik Metotlara sınıf adı ile ulaşılır. Örneğin
aşağıdaki Topla() metodu statik olarak tanımlanmış ve Main() metodu içersinden çağrılmıştır.

class cebir
{
    public static int Topla(params int[] dizi)
    {
        int toplam = 0;
        for (i = 0; i < dizi.Length; i++)
            toplam += dizi[i];
        return toplam;
    }
}

class Anasinif
{
    static void main()
    {
        int i;
        i = cebir.Topla(5, 6, 8);
        Console.Write(i);
    }
}


gördüğümüz gibi Cebir sınıfından herhangi bir nesne tanımlanmadan Topla() metoduna ulaştık.


Peki statik bir metoda nesne üzerinden erişmemiz mümkün mü? Hayır, mümkün değil. Örneğin aşağıdaki c nesnesi üzerinden
Topla() metoduna erişmeye çalışmak hatalıdır.
Cebir c= new cabir();
c.Topla(5,6,8);

Sınıflarımızı tanımlarken nesneler ile doğrudan iş yapmayan metotları statik olarak bildirmemiz gerekir.


Şu ana kadar yaptığımız tüm örneklerde main metodunun statik olarak tanımlamıştık. bunun nedeni main metodunun çalışması
için herhangi bir sınıf nesnesine ihtiyaç duymadan çalışmasını sağlamaktır.

Static anahtar sözcüğünü kullanırken erişim belirleyiciden önce veya sonra koymamız fark yaratmaz.





Bir statik metot içersinden sınıfn diğer statik metotları çağrılabilir. Ancak normal bir üye metot çağrılamaz.
Çünkü normal metotlar nesneler üzerinden işlem yaparlar. dolayısıyla nesnelerin adresleri gizlice metoda this referansı ile
gönderilir. Ancak statik metotlar sınıfın global metotlar olduğu için this referansları yoktur.

aşağıdaki bildirim geçerlidir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication12
{
    class Program
    {
         static void   Main()
        {
            metot2();
            Console.ReadLine();
        }
        public static void metot1()
        {
         
            Console.WriteLine("metot1");
        }

        public static void metot2()
        {
            metot1();
            Console.WriteLine("metot2");
        }

     
    }
}
// ekrana metot1 metot2 yazar.

eğer metot içerisinden cağırılan metot static değil iste nesne üzerinden çağırılmalıdır.
aşağıdaki örnek gibi;



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication12
{
    class Program
    {
         static void  Main()
        {
            metot2();
            Console.ReadLine();
        }
        public void metot1()
        {
         
            Console.WriteLine("metot1");
        }

        public static void metot2()
        {
            Program c = new Program();
            c.metot1();

            Console.WriteLine("metot2");
        }

     
    }
}
// ekrana metot1 metot2 yazar.





Statik olan bir metot statik olmayan bir metot içersinden çağırabilinir. yani çağırılan metodun statik olması gerekir
aşağıdaki örnekte görebilirsiniz.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace statikler
{
    class Program
    {
         static void   Main()
        {
            Program c = new Program();

             c.metot2();
             Console.ReadLine();
        }
        public static void metot1()
        {
         
            Console.WriteLine("metot1");
        }

        public  void metot2()
        {
            metot1();
            Console.WriteLine("metot2");
        }

     
    }



kısaca statik olarak tanımlanan bir metot herhangi bir metot içersinden nesne oluşturulmadan cağırılabilinir.




STATİK YAPICI METOTLAR



Normal metotlar gibi yapıcı metotlarda statik olabilir. Statik yapıcı metotlar bir sınıfın statik değişkenleri ile ilgili
işlemler yapmada kullanılır. Bir nesne ilk defa yaratıldığında statik üye değişkenini değiştirmek için genellikle statik
yapıcı metotlar tanımlanır. Statik olan bir metot ile statik olmayan bir değişkeni değiştirmek nasıl mümkün değil ise
statik olan yapıcılarda statik olmayan değişkenleri değiştiremez.

Statik metotların bildirilmesi normal metotların bildirim ile aynıdır. Sadece bildirimin başına static sözcüğü eklenir.

aşağıdaki örneği ve çıktısını inceleyelim.

using system
{
 class oyuncu
  {
     puplic oyuncu()
     {
        console.writeline("Statik olmayan yapıcı");
     }
 
     static oyuncu()
     {
        console.writeline("Statik yapıcı");
     }
}

 class Anasınıf
  {
    puplic static void main()
     {
         oyuncu x = new oyuncu();
         oyuncu o = new oyuncu();
         console.readline();
     }
}

Bu programın çıktısı;

Statik yapıcı
Statik olmayan yapıcı
Statik olmayan yapıcı

şeklindedir.

Görüldüğü gibi o nesnesi oluşturulduğunda hem statik yapıcı metot hem de statik olmayan metot çağrılmıştır(önce statik yapıcı
metot çağrılmış). Ancak x nesnesi oluşturulduğunda sadece statik olmayan metot çağrılmıştır.

Statik yapıcı metotlar herhangi bir parametre almazlar. Yani parametreli statik yapıcı metot tanımlanamaz.
Statik yapıcı metotların erişim belirleyicileride yoktur.

Bir nesneyi hangi yapıcı metot ile oluşturursak oluşturalım satatik yapıcı metot mutlaka ilk nesne tanımlandığında çalışır.


Statik yapıcı metotlar genellikle statik değişkenler ile ilgili işlemler yapılır. Ama bu zorunlu değildir. Örneğin aşağıdaki
kaynak kodda her oyuncu nesnesi oluşturulduğunda statik Toplam değişkeni 1 artırılıyor ve her oyuncu değişkeni işlevini
bitirdiğinde yıkıcı işlev yardımıyla Toplam değişkeni 1 azaltılıyor.




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
    class Oyuncu
    {
        public static int Toplam;

        public Oyuncu()
        {
            Oyuncu.Toplam++;
        }
        static Oyuncu()
        {
            Toplam = 0;
        }

        ~Oyuncu()
        {
            Console.WriteLine("Bir oyuncu gitti...");
            Toplam--;
        }
    }
    class Anasinif
    {
 
        static void Main()
        {

            Oyuncu o = new Oyuncu();
            Console.WriteLine("toplam oyuncu = " + Oyuncu.Toplam);
            Oyuncu x = new Oyuncu();
            Console.WriteLine("toplam oyuncu = " + Oyuncu.Toplam);
 
        }      
    }
}


bu programın ekran görüntüsü aşağıdaki gibidir.

toplam oyuncu = 1
toplam oyuncu = 2
Bir oyuncu gitti...
Bir oyuncu gitti...