24 Nisan 2012 Salı

C# 'da OOP-7 Polymorphism (Çok Biçimlilik)

Merhaba arkadaşlar...
Kalıtımı anlatırken, base sınıfımızdaki istediğimiz herhangi bir metotu, bu sınıftan türemiş alt sınıflarda aynı şekilde kullanmak zorunda değiliz demiştik. Konuya girmeden önce sınıflarımız bir hatırlayalım. "OOP - Abstract" konulu makalemden devam ediyorum. "Abstract" tanımladığımız "urun" isimli base sınıfımızın son haline bir bakalım.

    public abstract class Urun
    {
        private string _urunAdi;
        private decimal _urunFiyati;
        private int _stokMiktari;
        public string UrunAdi
        {
            get { return this._urunAdi; }
            set { this._urunAdi = value; }
        }
        public decimal UrunFiyati
        {
            get { return this._urunFiyati; }
            set { this._urunFiyati = value; }
        }
        public int StokMiktari
        {
            get { return this._stokMiktari; }
            set { this._stokMiktari = value; }
        }
        public decimal KDVLiFiyatGoster()
        {
            return this._urunFiyati * 1.08M;
        }
    }
Örneğin gelin "KDVLiFiyatGoster" metodunu farklı davrandıralım. Farklı davrandırabilmek için base sınıfındaki "KDVLiFiyatGoster" mototumu "virtual" keyword 'ü ile tanımlamalıyım. "Virtual" tanımlanmamış bir metot diğer sınıflarda farklı davrandırılamaz.
       
        public virtual decimal KDVLiFiyatGoster()
        {
            return this._urunFiyati * 1.08M;
        }

Şimdi bu metodumu "urun" sınıfını miras alan sınıflarda değişik şekilde kullanabilirim. Base sınıfımı miras alan "bilgisayar" ve "telefon" adında iki tane de türemiş sınıfım mevcuttu. Base sınıfındaki bir metotu, bu sınıfı miras alan alt sınıflarda değiştirme işlemine "override etme" yada "metot ezme" işlemi denir. Değiştirilecek olan metot yani ezilecek olan metot, base sınıfında "virtual" tanımlanmalı; türemiş sınıflarda ise bu metot "override" olarak tanımlanmalıdır.
Bu şemada "KDVLiFiyatGoster" metotu dışındaki metotlar, "object" sınıfındaki "virtual" tanımlanmış yani ezilebilir metotlardır. Önceki yazılarında da dedeğim gibi "tüm sınıflar object sınıfından türer". Bu senaryoda "object" sınıfından "urun" sınıfı, "urun" sınıfından da "bilgisayar" sınıfı türemiştir. Yani "urun" sınıfında, "object" sınıfındaki "virtual" tanımlanan metotları "override" edebilirim. "bilgisayar" sınıfında ise miras aldığı tüm sınıflardaki "virtual" tanımlanan metotları "override" edebilirim.

Şimdi "bilgisayar" sınıfımda "KDVLiFiyatGoster()" metotumun "override" edilmiş haline bir bakalım: 

        public override decimal KDVLiFiyatGoster()
        {
            return base.KDVLiFiyatGoster();
        }

"Override" ettim. Fakat bu haliyle "base" sınıfındaki "KDVLiFiyatGoster()" metotu çalışacaktır. Bu metotun içini (gövdesini) değiştirebilirim. Ürün fiyatını 1.08 ile değilde 1.18 ile çarpmak istiyorum. "Bilgisayar" ve "telefon" sınıflarının içinde bu metotun değiştirilmiş son hallerini görelim.

    public class Bilgisayar : Urun
    {
        private int _diskRPMHizi;
        public int DiskRPMBilgisi
        {
            get { return this._diskRPMHizi; }
            set { this._diskRPMHizi = value; }
        }

        public override decimal KDVLiFiyatGoster()
        {
            return this._UrunFiyati * 1.18M;
        }
    }

    public class Telefon : Urun
    {
        private float _kameraPikseli;
        public float KameraPikseli
        {
            get { return _kameraPikseli; }
            set { _kameraPikseli = value; }
        }
        private bool _bluetooth;
        public bool Bluetooth
        {
            get { return _bluetooth; }
            set { _bluetooth = value; }
        }

        public override decimal KDVLiFiyatGoster()
        {
            return this._UrunFiyati * 1.28M;
        }
    }
"Bilgisayar" sınıfımda kdv oranı yüzde 18, "telefon" sınıfımda ise yüzde 28 olsun istedim. Halbuki "urun" sınıfımda bu oran yüzde 8 'di. Bu metodumu farklı davrandırmış oldum.

METOT GİZLEME
"Peki farklı davrandırmasaydık da metodu yeniden yazsaydık olmaz mıydı?" sorusunu duyar gibiyim. Tüm sınıflarımızdaki metotlarımızdan "override" ve "virtual" keyword 'lerini kaldıralım. Noldu? Hem "base" hem de "derived" sınıflarında aynı isimde üç tane metot oldu. Hangi sınıfın instance 'ı ile çalışıyorsanız o sınıftaki metot çalışacaktır. (Tabi ki "urun" sınıfının instance 'ının alınabilmesi için, "abstract" tanımlanmamış olması gerekir.) Örneğin "bilgisayar" sınıfından instance alındığında:

            Bilgisayar bilgisayar=new Bilgisayar();
            bilgisayar.KDVLiFiyatGoster();

"bilgisayar" sınıfındaki metot çalışacaktır. Böylelikle "base" sınıfı olan "urun" sınıfındaki metot çalışmayacak, gölgelenecektir. Bu kullanıma "metot gizleme" denir. 

"Polymorphizm" tekniğini, "Metot gizleme" tekniğinden ayıran en büyük fark ise:
  • "Metot gizleme" 'de metot hangi sınıf instance 'ı üzerinden çağırılmışsa, o sınıftaki metot çalışacaktır. 
  • "Polymorphizm" tekniğinde ise metot, hangi sınıfın instance 'ı üzerinden çağırılırsa çağırılsın, metot en son hangi sınıfta "override" edilmişse oradaki haliyle çalışır.
Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

Hiç yorum yok:

Yorum Gönder