-- Tasarım Kalıpları ve Prensipleri

Liskov’un Yerine Geçme Prensibi – Liskov Substitution Principle (LSP)

LSP, aynı sınıftan türetilen sınıfların birbiri yerine rahatça kullanılabilmesini amaçlayan prensiptir. 

Aynı base sınıftan üretilen tüm alt sınıflar, birbirlerinin yerine kullanılabilir olmalıdır. Alt sınıflara özel bir istisnai durum kesinlikle oluşmamalıdır. Alt sınıflardan oluşan nesnelerin üst sınıfın nesneleri ile yer değiştirdikleri zaman, aynı davranışı sergilemelidir.

Bu doğrultuda aşağıdaki şekilde bir Dikdortgen sınıfımız ve basit bir AlanHesapla metodumuz olsun.

public class Dikdortgen
   {
       public int Genislik { getset; }
       public int Yukseklik { getset; }
 
       public Dikdortgen(int genislik, int yukseklik)
       {
           this.Genislik = genislik;
           this.Yukseklik = yukseklik;
       }
 
       public override string ToString()
       {
           return $"Dikdörtgen({Genislik},{Yukseklik})";
       }
   }
class Program
 {
     public static int AlanHesapla(Dikdortgen dikdortgen) => dikdortgen.Genislik * dikdortgen.Yukseklik;
 
     static void Main(string[] args)
     {
         Dikdortgen dikdortgen = new Dikdortgen(53);
 
         Console.WriteLine($"{dikdortgen} alanı = {AlanHesapla(dikdortgen)}");
         Console.ReadKey();
 
     }
 }

Bu programı çalıştırdığımızda göreceğimiz beklediğimiz gibi şu şekilde :

Dikdörtgen(5,3) alanı = 15

Buraya kadar herşey tamam ancak bir kare sınıfı oluşturalım. Her kare bir dikdörtgen olduğu için de bu sınıfı elimizdeki dikdörtgen sınıfından türetelim.

public class Kare : Dikdortgen
 {
     public new int Genislik
     {
         set
         {
             base.Yukseklik = base.Genislik = value;
         }
         get
         {
             return base.Genislik;
         }
       
     }
 
     public new int Yukseklik
     {
         set
         {
             base.Yukseklik = base.Genislik = value;
         }
         get
         {
             return base.Yukseklik;
         }
        
         
     }
 
     public Kare()
     {
 
     }
 
     public Kare(int genislik, int yukseklik) : base(genislik, yukseklik)
     {
         this.Genislik = genislik;
         this.Yukseklik = yukseklik;
     }
 
     public override string ToString()
     {
         return $"Kare({Genislik},{Yukseklik})";
     }
 }

Aşağıdaki şekilde programı çalıştıralım.

class Program
{
    public static int AlanHesapla(Dikdortgen dikdortgen) => dikdortgen.Genislik * dikdortgen.Yukseklik;
 
    static void Main(string[] args)
    {
        Kare kare = new Kare();
        kare.Genislik = 5;
 
        Console.WriteLine($"{kare} alanı = {AlanHesapla(kare)}");
        Console.ReadKey();
 
    }
}

Burada da alacağımız çıktı şu şekilde : Kare(5,5) alanı = 25

Fakat Kare nesnesini oluşturduğumuz satırı değiştirip referans tipini Dikdortgen olarak verdiğimizde program istenilen şekilde çalışmayacaktır.

class Program
   {
       public static int AlanHesapla(Dikdortgen dikdortgen) => dikdortgen.Genislik * dikdortgen.Yukseklik;
 
       static void Main(string[] args)
       {
           Dikdortgen dikdortgen = new Kare(); // referans tipini Dikdortgen verirsek
                                   // program istenilen şekilde çalışmaz.
           dikdortgen.Genislik = 5;
 
           Console.WriteLine($"{dikdortgen} alanı = {AlanHesapla(dikdortgen)}");
           Console.ReadKey();
 
       }
   }

Burada da alacağımız çıktı şu şekilde : Kare(5,0) alanı = 0

Kare sınıfının bir nesnesi oluşmasına rağmen görüldüğü üzere program LSP’ye aykırı bir tutum sergiliyor, prensibe göre alt sınıfın nesnesini üst sınıfınkiyle rahatlıkla değiştirebiliyor ve istediğimiz çıktıyı alabiliyor olmamız gerekirdi. Bunu virtual ve override anahtar sözcüklerini kullanarak düzeltelim ve prensip dışına çıkmadan kodumuzu yazmış olalım. Kodun tamamı şu şekilde :

namespace DesignPatternsTutorial
{
    public class Dikdortgen
    {
        public virtual int Genislik { getset; }
        public virtual int Yukseklik { getset; }
 
        public  Dikdortgen()
        {
        }
 
        public Dikdortgen(int genislik, int yukseklik)
        {
            this.Genislik = genislik;
            this.Yukseklik = yukseklik;
        }
 
        public override string ToString()
        {
            return $"Dikdörtgen({Genislik},{Yukseklik})";
        }
    }
 
    public class Kare : Dikdortgen
    {
        public override int Genislik
        {
            set
            {
                base.Yukseklik = base.Genislik = value;
            }
            get
            {
                return base.Genislik;
            }         
        }
 
        public override int Yukseklik
        {
            set
            {
                base.Yukseklik = base.Genislik = value;
            }
            get
            {
                return base.Yukseklik;
            }      
        }
 
        public Kare()
        {
        }
        public Kare(int genislik, int yukseklik) : base(genislik, yukseklik)
        {
            this.Genislik = genislik;
            this.Yukseklik = yukseklik;
        }
 
        public override string ToString()
        {
            return $"Kare({Genislik},{Yukseklik})";
        }
    }
 
    class Program
    {
        public static int AlanHesapla(Dikdortgen dikdortgen) => dikdortgen.Genislik * dikdortgen.Yukseklik;
 
        static void Main(string[] args)
        {
            Dikdortgen dikdortgen1 = new Kare(); 
            dikdortgen1.Genislik = 5;
            Dikdortgen dikdortgen2 = new Dikdortgen();
            dikdortgen2.Genislik = 4;
            dikdortgen2.Yukseklik = 8;
            Console.WriteLine($"{dikdortgen1} alanı = {AlanHesapla(dikdortgen1)}");
            Console.WriteLine($"{dikdortgen2} alanı = {AlanHesapla(dikdortgen2)}");
            Console.ReadKey();
 
        }
    }
}

Kare(5,5) alanı = 25
Dikdörtgen(4,8) alanı = 32

 

Bunu paylaş :

Yorum bırak

Yorum