Wednesday, October 31, 2012

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.

No comments:

Post a Comment