şükela:  tümü | bugün
  • "deadly diamond of death" de denilen yazılım mimarisinden kayaklanan "object oriented programming" ile ilgili bir problemdir. mesela doğadaki hayvanları ifade eden "hayvanlar alemi" diye bir sınıfımız olsun. bu "hayvanlar alemi" sınıfının altında bundan kalıtım yoluyla türetilmiş "kedi" ve "köpek" diye iki sınıfımız daha olsun. örneğimizde "hayvanlar alemi" sınıfına "yemekye()" diye bir metod oluşturalım. "kedi" sınıfının kendine has yemek yeme özelliği vardır. bu nedenle "hayvanlar alemi" sınıfının "yemekye()" metodunu "override" yaparak kendine has yemek yeme metodunu oluşturuyoruz. ayni şekilde "köpek" sınıfının da kendine has yemek yeme özelliği vardır. bunun için de "hayvanlar alemi" sınıfının "yemekye()" metodunu "override" ediyoruz. buraya kadar her şey yolunda gidiyor. kedi kendisine has yemek yeme özelliğine sahip, köpek de kendisine has yemek yeme özelliğine sahip. bunun dışında tüm hayvanların da yemek yeme özelliği kalıtım yoluyla diğer hayvan türlerine aktarılmak üzere mevcut duruyor. fakat ileride evde beslemek üzere "evhayvanlari" adında bir sınıf daha yaratırsak ne olur? elbette tüm hayvanlar ev hayvanı değildir o nedenle "evhayvanlari" sınıfını "hayvanlar alemi" sınıfından değil de "kedi" ve "köpek" sınıflarından kalıtım yoluyla türetmemiz gerekecek. bunu türettikten sonra ev hayvanlarına "yemekye()" metodunu oluşturmamız gerekecek çünkü ev hayvanları, mesela kedi doğada yasayan vahşi hemcinslerinden farklı yemek yeme davranışına sahip. ayni şekilde köpek de. simdi bizim bu "evhayvanlari" iki sınıftan türetildi bunlar "kedi" ve "köpek", ikisi de "yemekye()" metoduna sahip. eğer ev hayvanımıza yemek ye dersek bu ev hayvani kedi gibi yemek ye metodunu mu çalıştıracak yoksa köpek gibi mi? bu bir cikmaz, "hayvanlaralemi" sinifindan cikan iki dal "kedi" ve "köpek" diye ayrildi ama tekrar bu dallar "evhayvanlari" sinifinda birlesti, tipki bir baklava dilimi sekli gibi <> yada elmas (diamond) sekli gibi birlesti. bu durum özel olarak cözüm üretilmesi gereken bir problem.

    işte bu problemle karşılaşmamak için java dili iki ayrı sınıftan kalıtım almayı engellemiştir yani java dilinde "multiple inheritance" yoktur. ta ki "java 8"'e kadar. java 8 de "interface"ler de "uygulanmış" yani kod barındıran metodlar barındırabilir. elbet javada "extends" anahtar kelimesi ile sadece bir sınıftan inheritance yapabiliyoruz. ama bu interface kullanımında böyle değildir, bir sınıf birçok "interface"'i "implements" anahtar kelimesi ile uygulayabilir. java 8 e kadar "interface"'ler metod barındırmadığı için bir mimari sözleşme veya yaptırım olarak görev almış fakat java 8 de "interface"'ler metod barındırabilmesi ile işlevsellik kazanmıştır. bu da "diamond problem" başka bir deyişle "deadly diamond of death" problemini oluşturulabilir kılmıştır.
  • multiple inheritance'ın yol açtığı bir problem. bu problemin izahı bir örnek ile yapılabilir. elimizde 3 farklı tipte sınıf olduğunu düşünelim:

    - class_a: base (temel) sınıf
    - class_b ve class_c: class_a'dan türetilen iki farklı (derived) sınıf
    - class_d: temel sınıftan türetilen iki farklı sınıftan inherit alan bir başka türetilen (derived) sınıf

    class_a içerisinde speak adında bir metot olsun. class_b ve class_c, class_a'daki speak metodunu override (ezerek) ederek speak metodunu çağıracak. class_d ise, class_b ve class_c'nin speak metodunu override (ezerek) ederek hem class_b'deki hem de class_c'deki speak metodunu çağıracak.

    class class_a:
    ....def speak(self):
    ........print("class_a sinifindan cagirildi")

    class class_b(class_a):
    ....def speak(self):
    ........print("class_b sinifindan cagirildi")
    ........class_a.speak(self)

    class class_c(class_a):
    ....def speak(self):
    ........print("class_c sinifindan cagirildi")
    ........class_a.speak(self)

    class class_d(class_b, class_c):
    ....def speak(self):
    ........print("class_d sinifindan cagirildi")
    ........class_b.speak(self)
    ........class_c.speak(self)

    my_class = class_d()
    my_class.speak()

    buradaki sorun şu; biz base (temel) sınıftaki speak metodunun bir kere çağırılmasını beklerken iki kere çağırılmış oldu. aslında yapmak istediğimiz şey (ve multiple inheritance ile akılda tutulması gereken ilk kural) sınıf hiyerarşisi içerisinde bir sonraki metodun çağırılması fakat bu problem nedeni ile biz parent (ebeveyn) metodu çağırmış olduk. python dilinde bu problem super() ile çözülüyor.

    class class_a:
    ....def speak(self):
    ........print("class_a sinifindan cagirildi")

    class class_b(class_a):
    ....def speak(self):
    ........print("class_b sinifindan cagirildi")
    ........super().speak()

    class class_c(class_a):
    ....def speak(self):
    ........print("class_c sinifindan cagirildi")
    ........super().speak()

    class class_d(class_b, class_c):
    ....def speak(self):
    ........print("class_d sinifindan cagirildi")
    ........super().speak()

    my_class = class_d()
    my_class.speak()

    artık base (temel) sınıfımızdaki speak metodu bir kere çağırılıyor. burada dikkat edilmesi gereken nokta sınıf hiyerarşisinin (bkz: method resolution order) sondan başa doğru işlemesidir. multiple inheritance kullanırken bu tip problemler ile karşılaşmamak için sınıflarınızı iyi tasarlamanız gerekmektedir. oluşacak herhangi bir bug nedeniyle yapacağınız herhangi bir işlemi iki kere yapmış olabilirsiniz.

    * örnekler python 3 için geçerlidir. aşağıda python 2 için çözümü de bulabilirsiniz.
    https://git.io/vwggb
  • c++, common lisp vb. multiple inheritance destekleyen, görece eski ve oop paradigmasını kendi potasında eritmiş programlama dillerinde karşılaşılan bir problemdir. java, c# gibi, benzer programlama paradigmalarını destekleyen, nispeten yeni programlama dillerinin tasarımında multiple inheritance'dan kaçınıldığı için böyle bir problem yoktur. bu tarz programlama dillerinde ise çoklu türetmeye benzer bir etki yaratmak maksadıyla, tek bir base class'dan türetmeye* ve çoklu arayüz (bkz: interface) kullanımı* ile türetilen sınıfı dekore etmeye izin verilmiştir.

    peki, bu duruma bjarne stroustrup'un tepkisi ne olmuştur? kendisiyle yapılan bir röportajda konuyla ilgili olarak:

    " i'm very comfortable with multiple inheritance and i know many example that - in my opinion - cannot be done elegantly without multiple inheritance. "

    demiş ve yoluna devam etmiştir. şuradan okunabilir.