Çoklu kalıtım kullanım örnekleri


15

Java, dili basit tutmak için tasarım amacını ortadan kaldırdığı gerekçesiyle çoklu kalıtımı atlar .

Java'nın (eko-sistemi ile) gerçekten "basit" olup olmadığını merak ediyorum. Python karmaşık değildir ve birden fazla mirasa sahiptir. Yani çok öznel olmadan sorum şu:

Birden fazla kalıtımın yoğun kullanımını sağlamak için tasarlanmış bir koddan yararlanan tipik sorun modelleri nelerdir?


8
Java, çok az nedenden ötürü çok iyi şeyleri ihmal eder. MI için iyi bir gerekçe beklemiyordum.
DeadMG

2
Python'un çoklu mirası kesinlikle burada ejderha bölgesi. O kullandığı gerçeği derinliği ilk sola-sağa ad çözümlemesi sürdürülebilirlik ve anlama ikisi için önemli sorunlar vardır. Sığ sınıf hiyerarşilerinde yararlı olabilse de, derin olanlarda inanılmaz derecede sezgisel olabilir.
Mark Booth

Java'nın birden fazla miras içermemesinin sebebi, Java geliştiricilerinin dillerinin öğrenilmesini kolay olmasını istediğidir. Birden fazla miras, bazı durumlarda inanılmaz derecede güçlü olsa da, kavranması zordur ve iyi bir etki için kullanılması daha zordur; programlama birinci sınıf öğrencisi ile yüzleşmek isteyeceğiniz bir şey değildir. Demek istediğim: Kalıtım kavramıyla mücadele eden birine sanal kalıtımı nasıl açıklıyorsunuz? Ve, birden fazla kalıtım da uygulayıcılar tarafında tam olarak önemsiz olmadığından, Java geliştiricisi muhtemelen bunu atlamanın bir kazan-kazan olmasına rağmen.
cmaster - eski haline monica

Java nominal olarak yazılmıştır. Python değil. Bu, çoklu kalıtımın Python'da uygulanması ve anlaşılmasını çok daha kolay hale getirir.
Jules

Yanıtlar:


11

Artıları:

  1. Bazen bir problemi modellemenin diğer yollarından daha belirgin bir şekilde modellenmesine izin verir.
  2. Farklı ebeveynlerin dikey amacı varsa, bir çeşit kompozisyona izin verebilir

Eksileri :

  1. Eğer farklı ebeveynlerin dikey bir amacı yoksa, tipin anlaşılmasını zorlaştırır.
  2. Bir dilde (herhangi bir dilde) nasıl uygulandığını anlamak kolay değildir.

C ++ 'da, dikey özellikleri birleştirmek için kullanılan çoklu kalıtımın iyi bir örneği, örneğin bir oyun için bir bileşen sistemi kurmak için CRTP kullandığınız zamandır .

Bir örnek yazmaya başladım, ancak gerçek dünya örneğine bakmaya değer olduğunu düşünüyorum. Bazı Ogre3D kodu, güzel ve çok sezgisel bir şekilde çoklu kalıtım kullanır. Örneğin, Mesh sınıfı hem Kaynaklar'dan hem de AnimationContainer'dan miras alır. Kaynaklar tüm kaynaklarda ortak olan arayüzü ve AnimationContainer bir dizi animasyonu işlemek için özel arayüzü ortaya koyar. İlişkili değillerdir, bu nedenle Mesh'i bir dizi animasyon da barındırabilecek bir kaynak olarak düşünmek kolaydır. Doğal geliyor değil mi?

Sınıfları yeni bir aşırı yükleme ve silme CRTP sınıfının varyantlarından miras alarak bellek ayırma işleminin taneli bir şekilde yönetilmesi gibi diğer örneklere bakabilirsiniz .

Söylendiği gibi, çoklu kalıtımla ilgili temel sorunlar, ilgili kavramların karıştırılmasından kaynaklanmaktadır. Bu dil karmaşık uygulamalar (C ++ elmas sorunu ile oynamak için izin verir nasıl ...) ayarlamak zorunda yapar ve kullanıcı bu uygulamada neler olduğundan emin değil. Örneğin, C ++ ile nasıl uygulandığını açıklayan bu makaleyi okuyun .

Dili dilden kaldırmak, dilin işleri kötü yapmak için nasıl uygulandığını bilmeyen insanlardan kaçınmaya yardımcı olur. Ancak, bazen doğal hissetmeyecek şekilde düşünmeye zorlar, uç durumlar olsa bile, daha sık düşünebileceğiniz şey olur.


Cevabınızı örnek bir problemle
süslerseniz çok memnun olurum

Tamam, bir şey eklemeye çalışayım.
Klaim

Ogre3D, tasarım ilhamı için bakacağım bir yer değil - Singleton enfeksiyonunu gördünüz mü?
DeadMG

Birincisi, varis single'ı gerçekten bir singleton değil, inşaat ve yıkım açık. Daha sonra Ogre, bir donanım sistemi (veya isterseniz grafik sürücüsü) üzerindeki bir katmandır. Bu, sistem arabirimleri için (Kök veya diğerleri gibi) yalnızca tek bir benzersiz temsil olması gerektiği anlamına gelir. Bazı singletonları kaldırabilirler ama buradaki nokta bu değil. Bir trol tartışması yapmaktan kaçınmak için bunu gönüllü olarak kullanmaktan kaçındım, bu yüzden lütfen işaret ettiğim örneklere bakın. Singleton kullanımları mükemmel olmayabilir, ancak pratikte açıkça yararlıdır (ancak her şey için değil, sadece kendi sistemi için).
Klaim

4

Daha dinamik dillerde yoğun olarak kullanılan mixins adı verilen bir kavram var . Çoklu kalıtım, karışımların bir dil tarafından desteklenmesinin bir yoludur. Karışımlar genellikle bir sınıfın farklı işlev parçalarını biriktirmesinin bir yolu olarak kullanılır. Birden fazla miras olmadan, biraz daha sözdizimi ağır olan bir sınıfla mixin türü davranış elde etmek için toplama / temsilci kullanmanız gerekir.


+1 bu aslında çoklu kalıtsallığa sahip olmak için iyi bir nedendir. Mixins ek çağrışımlar taşır ("bu sınıf tek başına kullanılmamalıdır")
ashes999

2

Bence seçim esas olarak elmas sorunu nedeniyle sorunlara dayanmaktadır .

Ayrıca, birden fazla miras kullanımının delegasyonla veya başka yollarla atlatılması genellikle mümkündür.

Son sorunuzun anlamından emin değilim. Fakat eğer "hangi durumlarda çoklu kalıtım yararlıdır?"


2

Burada çok fazla uğraşmayacağım ama http://docs.python.org/release/1.5.1p1/tut/multiple.html bağlantısını kullanarak python'daki çoklu mirası kesinlikle anlayabilirsiniz :

Anlambilimi açıklamak için gereken tek kural, sınıf özniteliği başvuruları için kullanılan çözümleme kuralıdır. Bu, önce derinlik, soldan sağa. Böylece, bir öznitelik DerivedClassName içinde bulunmazsa, Base1'de, sonra (yinelemeli olarak) Base1 temel sınıflarında aranır ve yalnızca orada bulunmazsa, Base2'de aranır vb.

...

Birden fazla mirasın ayrım gözetmeden kullanılmasının, Python'da kazara isim çatışmalarından kaçınmak için sözleşmelere güvenmesi nedeniyle bir bakım kabusu olduğu açıktır. Çoklu kalıtımla ilgili iyi bilinen bir sorun, ortak bir temel sınıfa sahip olan iki sınıftan türetilmiş bir sınıftır. Bu durumda ne olacağını anlamak kolay olsa da (örneğin, `` örnek değişkenleri '' nin tek bir kopyası veya ortak temel sınıf tarafından kullanılan veri öznitelikleri olacaktır), bu anlambilimin herhangi bir şekilde olduğu açık değildir. işe yarar.

Bu sadece küçük bir paragraf ama sanırım şüpheleri giderecek kadar büyük.


1

Birden fazla kalıtımın yararlı olacağı bir yer, bir sınıfın birkaç arabirim uyguladığı bir durumdur, ancak her arabirimde bazı varsayılan işlevlerin yerleşik olmasını istersiniz. Bazı arabirimleri uygulayan sınıfların çoğu aynı şekilde bir şey yapmak istiyorsa, ancak bazen farklı bir şey yapmanız gerektiğinde yararlıdır. Her bir sınıfı aynı uygulamaya sahip olabilirsiniz, ancak onu tek bir konuma itmek daha mantıklıdır.


1
Bu, genelleştirilmiş çoklu devralma mı yoksa basitçe bir arabirimin uygulanmayan yöntemler için varsayılan davranışları belirleyebileceği bir yöntem mi gerektirir? Arabirimler yalnızca kendi uyguladıkları yöntemler için varsayılan uygulamaları belirleyebilseydi (diğer arabirimlerden miras aldıklarının aksine) böyle bir özellik, çoklu kalıtımı zorlaştıran çift elmas sorunlarından tamamen kaçınırdı.
supercat

1

Çoklu kalıtımın yoğun kullanımını sağlamak için tasarlanmış bir koddan yararlanan tipik sorun kalıpları nelerdir?

Bu sadece bir örnektir, ancak güvenliği arttırmak ve arayanlar veya alt sınıflar boyunca basamaklı değişiklikler uygulamak için cazipleri azaltmak için çok değerli bulduğum bir örnek.

En soyut, durumsuz arayüzler için bile çoklu kalıtımın son derece yararlı bulduğum yerde, C ++'daki sanal olmayan arayüz deyimi (NVI).

Sözleşmelerin evrensel yönlerini uygulamak için kendilerine biraz uygulama yapan arayüzler kadar soyut temel sınıflar bile değiller, çünkü sözleşmenin genelliğini daha iyi uygulayacak kadar daraltmıyorlar. .

Basit bir örnek (bazıları iletilen bir dosya tanıtıcısının açık olduğunu veya bunun gibi bir şeyi kontrol edebilir):

// Non-virtual interface (public methods are nonvirtual/final).
// Since these are modeling the concept of "interface", not ABC,
// multiple will often be inherited ("implemented") by a subclass.
class SomeInterface
{
public:
    // Pre: x should always be greater than or equal to zero.
    void f(int x) /*final*/
    {
        // Make sure x is actually greater than or equal to zero
        // to meet the necessary pre-conditions of this function.
        assert(x >= 0);

        // Call the overridden function in the subtype.
        f_impl(x);
    }

protected:
    // Overridden by a boatload of subtypes which implement
    // this non-virtual interface.
    virtual void f_impl(int x) = 0;
};

Bu durumda, belki fkod tabanındaki bin yer tarafından çağrılırken, f_implyüz alt sınıf tarafından geçersiz kılınır.

Bu tür güvenlik kontrolünü çağıran her 1000 yerde fveya geçersiz kılan 100 yerde yapmak zor olacaktır f_impl.

Sadece bu girişi sanal olmayan işlevselliğe işaret ederek, bana bu kontrolü yapmak için tek bir merkezi yer verir. Ve bu kontrol, sadece bu işlevi çağırmak için gereken bir önkoşul olduğunu iddia ettiği için soyutlamayı en ufak bir şekilde azaltmaz. Bir bakıma, arayüz tarafından sağlanan sözleşmeyi tartışmalı olarak güçlendiriyor ve xgirişi geçersiz kılan tüm 100 yerde geçerli ön koşullara uyduğundan emin olmak için girişi kontrol etme yükünü hafifletiyor .

Her dilin C ++ 'da bile yerel bir kavramdan biraz daha fazla olmasını dilediğim bir şey (ör: geçersiz kılmak için ayrı bir işlev tanımlamamızı gerektirmez).

Bu assertönceden yapmadıysanız son derece kullanışlıdır ve daha sonra kod tabanındaki bazı rastgele yerlerin iletilen negatif değerlerle karşılaştığı zaman gerekli olduğunu fark ettiniz f.


0

İlk olarak: temel sınıfın birden çok kopyası (bir C ++ sorunu) ve temel ve türetilmiş sınıflar arasında sıkı bağlantı.

İkincisi: soyut arayüzlerden çoklu kalıtım


herhangi bir bağlamda yararlı olmadığını mı düşünüyorsunuz? Ve her şey onsuz uygun şekilde tasarlanabilir / kodlanabilir mi? Ayrıca lütfen ikinci noktaya dikkat edin.
treecoder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.