Published on

Liskov Substitution Prensibi Nedir ?

Authors
  • avatar
    Name
    Alperen Önal
    Twitter

Liskov prensibi, Barbara Liskov tarafından 1987 yılında tanıtılmıştır.

Liskov prensibini öncelikle Barbara'nın ağzından dinleyelim.

Φ(x), T tipindeki x nesneleri hakkında kanıtlanabilir bir özellik olsun. O halde Φ(y), S tipindeki y nesneleri için doğru olmalıdır; burada S, T'nin bir alt tipidir.

Barbara'nın sözünü daha açık ve anlaşılır hale getirmek için şöyle bir örnek verebiliriz :

  • Φ(x): x tipindeki nesneler için doğru olan bir özelliği ifade eder. Örneğin, x bir Hayvan nesnesi ise, sesCikar gibi bir özellik olabilir.
  • x: T tipindeki bir nesneyi temsil eder. Örneğin, Hayvan tipinde bir nesne.
  • T: Üst sınıf (base class). Örneğin, Hayvan sınıfı.
  • y: S tipindeki bir nesneyi temsil eder. Örneğin, Kedi tipinde bir nesne.
  • S: Alt sınıf (subclass). Örneğin, Kedi sınıfı, Hayvan sınıfının alt sınıfıdır.

Özetle Liskov Prensibi, Bir alt sınıfın(subclass) üst sınıfın (baseclass) tüm davranışlarını doğru şekilde devralması gerektiğini vurgular. Hayvan diye baseclass'ımız olsun, bu class'da "havla" isimli bir özellik bulunması bu prensibin ihlaline yol açacaktır çünkü "kedi" gibi bir alt sınıfın bu "havla" özelliğini alamayacağını biliyoruz.

Amaçlar :

  • Yerine geçebilirlik garantisi: Alt sınıfların, üst sınıfların yerlerine geçebilmesini garanti eder.
  • Hiyerarşik tutumluluk sağlanır.
  • Poliformizmi destekleyerek genişletilebilir bir hiyerarşi oluşturulmasına olanak sağlar.

Aşağıda IKus baseclass'ının, kodu incelediğimiz zaman fly() baseclass özelliğinin tüm subclass'lar ile uyumlu olmadığını görüyoruz. Çünkü penguen bir kuştur ancak uçamaz. İşte tam da burada Liskov prensibi ihlal ettiğini anlıyoruz.

interface IKus
{
    public void Fly();
    public void Yumurtla();
    public void Beslen();
    public void Diskila();
}

class Papagan : IKus
{
    public void Fly()
    {
        //uçuş işlemleri
    }
    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }

}


class Karga : IKus
{

     public void Fly()
    {
        //uçuş işlemleri
    }
    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }
}

class Penguen : IKus
{
     public void Fly()
    {
        //ben ucamiyorum.
        throw new NotImplementedException();
    }
    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }
}


Liskov prensibine uyumlu hale getirmemiz için baseclass'ın tüm özellikleri, subclass'lara uygulayabileceğimiz özellik olmalı yani açıkta kalmamalı.


Kuş; tüyleri, dişsiz gagaları, yumurtladıkları sert kabuklu yumurtalar yoluyla üreyen, yüksek metabolizma hızına sahip, dört odacıklı kalpleri ve hafif ama güçlü bir iskelet yapısına sahip, Aves sınıfını oluşturan sıcakkanlı omurgalı hayvanlar grubudur.

Wikipedia'nın bu metnine göre bütün kuşlar uçabilir diye bir şey demiyor. Ancak tüm kuşlar yumurtluyor. Ve haliyle beslenip dışkılayabiliyorlar. Buna göre kodu tekrar düzenleyecek olursak :



interface IKus
{

    public void Yumurtla();
    public void Beslen();
    public void Diskila();

}

class Papagan : IKus
{
    public void Fly()
    {
        //uçuş işlemleri
    }
    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }
}


class Karga : IKus
{
     public void Fly()
    {
        //uçuş işlemleri
    }
    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }
}


class Penguen : IKus
{

    public void Yumurtla()
    {
        //yumurtlama işlemleri
    }
    public void Beslen()
    {
        //beslenme işlemleri
    }
    public void Diskila()
    {
        //diskilama islemleri
    }

}


Evet, kodumuz artık Liskov'a uyumlu hale geldi. Artık IKus'daki herhangi bir özellik herhangi bir subclass'da açıkta kalmıyor.

Okuduğunuz için teşekkürler bir serinin kalanına devam etmeyi unutmayın :) İnterface Segregation Principle Nedir ?