Bu “mirasa karşı iyilik kompozisyonu” kavramı nereden geliyor?


143

Son birkaç ayda, "mirasa karşı iyilik kompozisyonu" mantığı hiçbir yerden fırlamış ve programlama topluluğu içinde neredeyse bir çeşit meme haline gelmiş gibi görünmektedir. Ve onu her gördüğümde biraz şaşırdım. Birinin dediği gibi "kırıcıların lehine matkaplar". Tecrübelerime göre, kompozisyon ve kalıtım, farklı kullanım durumlarına sahip iki farklı araç ve bunları birbirinin yerine geçiyormuş gibi ele alıyor ve biri doğası gereği diğerinden üstündü.

Ayrıca, kalıtımın neden kötü olduğu ve kompozisyonun iyi olduğu için gerçek bir açıklama görmüyorum , bu da beni daha da şüpheli kılıyor. Sadece inanca kabul edilmesi mi gerekiyor? Liskov ikame ve polimorfizminin iyi bilinen ve net faydaları vardır ve IMO, nesne yönelimli programlama kullanımının tüm noktasını oluşturur ve hiç kimse neden kompozisyon lehine atılmaları gerektiğini açıklamaz.

Bu kavramın nereden geldiğini ve arkasındaki mantığın ne olduğunu bilen var mı?


45
Diğerlerinin de belirttiği gibi, çok uzun zaman oldu - şu anda bunu duyduğunuza şaşırdım. Java gibi dillerde büyük sistemler bir süredir inşa eden herkes için sezgisel. Verdiğim röportajın temelini oluşturuyor ve bir aday miras hakkında konuşmaya başladığında, beceri seviyelerinden ve deneyim miktarlarından şüphe etmeye başladım. Kalıtımın
Janx

6
@Janx: Belki de budur. Java gibi dillerde büyük sistemler yapmıyorum; Onları Delphi'de yapıyorum ve Liskov ikame ve polimorfizm olmadan hiçbir şey yapamayız. Nesne modeli, Java ya da C ++ 'dan farklı şekillerde farklıdır ve Delphi'de bu maksimimin çözmesi gereken gibi görünen problemlerin çoğu yoktur ya da daha az problemlidir. Sanırım farklı açılardan farklı bakış açıları.
Mason Wheeler

14
Delphi'de nispeten büyük sistemler inşa eden bir ekipte uzun yıllar geçirdim ve uzun miras ağaçları kesinlikle ekibimizi ısırdı ve bize ciddi acı verdi. SOLID ilkelerine dikkatinizin, Delphi kullanımınızı değil, sorunlu alanlardan uzak durmanıza yardımcı olduğunu düşünüyorum.
Bevan

8
Son birkaç ay mı?
Jas

6
IMHO bu kavram hiçbir zaman hem arayüz kalıtımını (yani saf arayüzlerle alt yazma) hem de uygulama kalıtımını destekleyen dil çeşitliliğine tam olarak ayarlanmadı. Bu mantrayı çok fazla insan takip ediyor ve yeterince arayüz kullanmıyor.
Uri

Yanıtlar:


136

GoF'ten çok önce kompozisyon-miras miras tartışmaları duyduğumu düşünmeme rağmen, parmağımı belirli bir kaynağa koyamıyorum. Yine de Booch olmuş olabilir.

<Rant>

Ah, ancak birçok mantrada olduğu gibi, bu tipik çizgiler boyunca yozlaşmıştır:

  1. Bu, özgün karmaşık tartışmanın bir hatırlatıcısı olarak catch-cümlesini oluşturan saygın bir kaynak tarafından ayrıntılı bir açıklama ve argüman ile tanıtılır.
  2. Genellikle n00b hataları hakkında yorum yaparken, bir süredir bildiği birkaç kişi tarafından bilinen bir takımın göz kırpmasıyla paylaşılıyor
  3. çok geçmeden akılsızca binlerce kişi tarafından açıklamayı asla okumayan, ancak düşünmemek için bir bahane olarak ve başkalarından daha üstün hissetmek için ucuz ve kolay bir yol olarak kullanmayı seviyorum
  4. Sonunda, hiçbir makul borçlanma “meme” gelgitine neden olamaz - ve paradigma din ve dogmaya dönüşür.

Başlangıçta n00b'lerin aydınlanmasına öncülük etmesi amaçlanan meme şimdi bilinçsizce kendilerini kandırmak için bir kulüp olarak kullanılıyor.

Kompozisyon ve kalıtım çok farklı şeylerdir ve birbirleriyle karıştırılmamalıdır. Kompozisyonun birçok fazla çalışma ile mirası simüle etmek için kullanılabileceği doğru olsa da , bu mirası ikinci sınıf bir vatandaş yapmaz ve kompozisyonu favori oğlu yapmaz. Birçok n00b'nin devralmayı kısayol olarak kullanmaya çalışması, mekanizmayı geçersiz kılmaz ve neredeyse tüm n00b'ler hatadan ders alır ve böylece geliştirir.

Lütfen DÜŞÜNÜN senin tasarımları hakkında, sloganlar spouting durdurun.

</ Rant>


16
Booch, uygulama mirasının sınıflar arasında yüksek eşleşme sağladığını savunuyor. Öte yandan, mirası, OOP'yi prosedürel programlamadan ayıran anahtar kavram olarak görüyor.
Nemanja Trifunovic

13
Böyle bir şey için bir kelime olmalı. Erken Yetersizlik , belki?
Jörg W Mittag

8
@ Jörg: Erken Yetersizlik gibi bir terime ne olacağını biliyor musun? Tam olarak yukarıda açıklananlar. :) (Btw. Ne zaman yetersizlik zaman erken değil?)
Bjarke Freund-Hansen

6
@Nemanja: Doğru. Soru, bu eşleşmenin gerçekten kötü olup olmadığıdır. Sınıflar kavramsal olarak güçlü bir şekilde birleştirildiyse ve kavramsal olarak bir üst-alt tip ilişkisi oluşturduysa ve dil düzeyinde resmen ayrıştırılmış olsalar bile asla gebe kalmazlarsa, o zaman güçlü birleşme iyidir.
dsimcha

5
Mantra basittir, "sırf play-doh'u hiçbir şey gibi görünecek şekilde biçimlendirmeniz, her şeyi play-dohtan çıkarmanız gerektiği anlamına gelmez." ;)
Evan Plaice

73

Deneyim.

Sizin dediğiniz gibi onların farklı işlerin araçları olduklarını, ancak ifadenin ortaya çıktığını çünkü insanların bu şekilde kullanmadıklarını söyledi.

Kalıtım esas olarak polimorfik bir araçtır, ancak bazı insanlar, daha sonraki tehlikelerine rağmen, kodu yeniden kullanma / paylaşma yöntemi olarak kullanmaya çalışırlar. Gerekçe “iyi miras alırsam tüm yöntemleri bedavaya alırım” olmaktır, ancak bu iki sınıfın potansiyel olarak polimorfik bir ilişkiye sahip olmadığı gerçeğini görmezden gelin.

Öyleyse neden devralma üzerine kompozisyonu tercih edelim - basitçe sınıflar arasındaki ilişki polimorfik değildir. İnsanlara diz pisliğinin miras alarak yanıt vermemelerini hatırlatmak için basitçe var olur.


7
Bu yüzden, temel olarak, "Liskov ikamesini anlamıyorsanız, ilk başta OOP kullanmamalısınız" diyemezsiniz, bu yüzden, yetersiz olan tarafından verilen hasarı sınırlandırma girişimi yerine, "miras yerine kompozisyonu tercih edersiniz" diyorsunuz. kodlayıcılar?
Mason Wheeler

13
@Mason: Tüm mantralarda olduğu gibi, yeni başlayan programcılarda “kalıtımın iyiliğine karşı kompozisyon” hedefleniyor. Kalıtımın ne zaman ve ne zaman kompozisyon kullanılacağını zaten biliyorsanız, bunun gibi bir mantrayı tekrarlamak anlamsızdır.
Dean Harding,

7
@ Dean - Başlangıç seviyesinin kalıtımın en iyi uygulamalarını anlamayanla aynı olduğundan emin değilim . Bundan daha fazlası olduğunu düşünüyorum. Zayıf kalıtım, işimdeki birçok baş ağrısının sebebidir ve programcılar tarafından "yeni başlayanlar" olarak kabul edilecek kod değildir.
Nicole

6
@Renesis: Bunu duyduğumda ilk düşündüğüm şey, "bazı insanlar on yıllık deneyime sahip ve bazı insanlar on kez tekrarlanan bir yıllık deneyime sahip."
Mason Wheeler

8
İlk “O” Aldıktan hemen sonra oldukça büyük bir proje tasarlıyor ve yoğun olarak ona güveniyordum. İşe yaramasına rağmen, tasarımı sürekli olarak kırılgan buldum - burada ve orada küçük tahrişlere neden oluyor ve bazen belirli refaktörleri tam bir kaltak yapıyor. Tüm tecrübeyi açıklamak biraz zor, ancak "Mirasa Karşı Taahhüt Tazminatı" ibaresi tam anlamıyla açıklar. “Mirastan Kaçın” demediğini ve hatta ima etmediğini unutmayın, seçim açık olmadığında size biraz dürtme sağlar.
Bill K,

43

Bu yeni bir fikir değil, 1994'te yayımlanan GoF tasarım desenleri kitabında tanıtıldığına inanıyorum.

Kalıtımın asıl sorunu beyaz kutusudur. Tanım olarak, miras aldığınız sınıfın uygulama ayrıntılarını bilmeniz gerekir. Öte yandan, kompozisyonla, yalnızca oluşturduğunuz sınıfın ortak arabirimini önemsersiniz.

GoF kitabından:

Miras, ebeveyninin uygulamasının ayrıntılarına bir alt sınıf gösterir, genellikle 'mirasın kapsüllemeyi bozduğu' söylenir.

GoF kitabındaki wikipedia makalesinin iyi bir tanıtımı var.


14
Buna katılmıyorum. Miras aldığınız sınıfın uygulama ayrıntılarını bilmenize gerek yoktur; sadece sınıf tarafından maruz kalan kamu ve korunan üyeler. Uygulama ayrıntılarını bilmek zorundaysanız, o zaman siz ya da temel sınıfı kim yazdıysa, yanlış bir şey yapıyordur ve kusur ana sınıftaysa, kompozisyon onu düzeltmenize / çözmenize yardımcı olmaz.
Mason Wheeler

18
Okumadığınız bir şeye nasıl katılmıyorsunuz? GoF’un küçük bir görüntüsünü aldığınız tartışmaların bir kısmı ve sağlam bir sayfası var.
philosodad

7
@ pholosodad: Okumadığım bir şeyle aynı fikirde değilim. Dean'in yazdıklarına katılmıyorum, “Tanım gereği, miras aldığınız sınıfın uygulama ayrıntılarını bilmeniz gerekir” i okudum.
Mason Wheeler

10
Yazdıklarım GoF kitabında anlatılanların bir özetidir. Bunu biraz kuvvetle ifade etmiş olabilirim ( tüm uygulama detaylarını bilmenize gerek yok ) ancak GoF'un kalıtım konusundaki kompozisyonu tercih etmesinin genel nedeni budur.
Dean Harding,

2
Hatalıysam beni düzeltin, ancak "örtük (yani miras) yerine açık sınıf ilişkilerini (ör. Arayüzler) tercih et" olarak görüyorum. İlki, size nasıl yapılacağını söylemeden neye ihtiyacınız olduğunu söyler. İkincisi, yalnızca nasıl yapılacağını anlatmakla kalmaz, aynı zamanda yolda pişman olmanızı da sağlar.
Evan Plaice


23

"Mirasa ilişkin kompozisyon", "Bir sınıfın verilerinin (veya davranışının) başka bir sınıfa dahil edilmesi gerektiğini hissederken, her zaman mirası kör bir şekilde uygulamadan önce kompozisyonu kullanmayı düşünün" demesinin kısa (ve görünüşte yanıltıcı) bir yoludur.

Bu neden doğru? Çünkü kalıtım, 2 sınıf arasında sıkı, derleme zamanı birleşimi yaratır. Aksine, bileşim gevşek bağlantı olup, diğerleri arasında endişelerin net bir şekilde ayrılmasını, çalışma süresinde bağımlılıkların anahtarlanabilme olasılığını ve daha kolay, daha yalıtılmış bağımlılık test edilebilirliğini sağlar.

Bu sadece kalıtımın dikkatli kullanılması gerektiği anlamına gelir çünkü bir faydası yoktur, bir maliyeti vardır. Aslında, “mirasa ilişkin kompozisyon” genellikle “bağımlılıktan mirasa ilişkin miras” kompozisyonu anlamına gelir çünkü sık sık bağımlılığınızın somut alt sınıftan ziyade soyut bir üst sınıf olmasını istersiniz. Çalışma zamanında bağımlılığınızın farklı somut uygulamaları arasında geçiş yapmanızı sağlar.

Bu nedenle (diğerleri arasında), muhtemelen vanilya mirasından daha fazla arabirim uygulaması veya soyut sınıflar şeklinde kullanılan miras göreceksiniz.

(Mecazi) bir örnek olabilir:

"Bir Yılan sınıfım var ve Yılan ısırdığında ne olacağını bu sınıfın bir parçası olarak eklemek istiyorum. Yılanın Bite () yöntemine sahip bir BiterAnimal sınıfını miras alması ve zehirli ısırığı yansıtmak için bu yöntemi geçersiz kılması için cazip olacağım Fakat Miras Üzerine Kompozisyon beni bir kompozisyon kullanmaya çalışmam gerektiği konusunda uyarıyor ... Benim durumumda bu bir Bite üyesine sahip Snake'e çevrilebilir.Bite sınıfı birkaç alt sınıfa sahip soyut (veya bir arayüz) olabilir. VenomousBite ve DryBite alt sınıflarına sahip olmak ve yılanın yaşlandıkça aynı Snake örneğindeki ısırığı değiştirebilmek gibi güzel şeyler.Ayrıca, bir Bite'nın tüm etkilerini kendi sınıfında kullanmak, onu bu Frost sınıfında tekrar kullanmama izin verebilir , çünkü don ısırır, ancak bir BiterAnimal değildir, vb ... "


4
Yılan ile çok güzel bir örnek. Son zamanlarda kendi sınıflarımda benzer bir durumla karşılaştım
Maksee

22

Kompozisyon için bazı olası argümanlar:

Kompozisyon biraz daha fazla dil / çerçeve agnostik
Kalıtımdır ve neyi uygular / ister / sağlar / ne sağlar? Alt / üst sınıfın erişebildiği ve sanal yöntemleri olan performansları neler olabilir? çok az dil desteği ve dolayısıyla farklı platformlar / çerçevelerdeki uygulamalar kompozisyon desenlerini daha kolay paylaşabilir.

Kompozisyon nesneler inşa etmenin çok basit ve dokunsal bir yoludur
Kalıtımın anlaşılması kolaydır, fakat yine de gerçek hayatta olduğu gibi kolayca gösterilemez. Gerçek hayatta birçok nesne parçalara ayrılarak oluşturulabilir. Diyelim ki bir bisiklet iki tekerlek, bir çerçeve, bir koltuk, bir zincir vb. Kullanılarak yapılabilir. Bir kalıtım metaforunda, bir bisikletin bir tek tekerlekli sirk bisikletine uzandığını söyleyebilirim, bir miktar uygulanabilir ancak yine de gerçek görüntüden kompozisyondan çok daha ileride. (Açıkçası bu çok iyi bir kalıtım örneği değil, ama aynı kalır). Kalıtım kelimesi bile (en azından beklediğim çoğu ABD İngilizcesi konuşmacıları) bile, yazılımdaki anlamı ile bir bağlantısı olan, ancak yine de sadece gevşek bir şekilde uyuyan "ölmüş bir akrabadan bir şey geçti" çizgileri boyunca otomatik olarak bir anlam ifade ediyor.

Kompozisyon neredeyse her zaman daha esnektir Kompozisyonu
kullanarak her zaman kendi davranışınızı tanımlamayı seçebilir veya yalnızca kompozisyon bölümlerinizin o bölümünü gösterebilirsiniz. Bu şekilde miras hiyerarşisi (sanal vs sanal olmayan vb.) Tarafından getirilebilecek hiçbir kısıtlama ile karşılaşmazsınız.

Öyleyse, Kompozisyon doğal olarak kalıtımdan daha az teorik kısıtlamaları olan daha basit bir metafor olabilir. Ayrıca, bu özel nedenler tasarım süresi boyunca daha belirgin olabilir veya kalıtımın bazı acı noktalarıyla uğraşırken ortaya çıkabilir.

Yasal Uyarı:
Açıkçası bu kesin değil / tek yönlü bir cadde değil. Her tasarım, çeşitli kalıpların / araçların değerlendirilmesini hak eder. Kalıtım yaygın olarak kullanılır, birçok faydası vardır ve çoğu zaman kompozisyondan daha şıktır. Bunlar, kompozisyonu tercih ederken kullanılabilecek bazı olası nedenlerdir.


1
"Açıkçası bu kesin değil / tek yönlü bir cadde değil." Kompozisyon, kalıtımdan daha fazla (veya aynı derecede) esnek değildir; Ben bunu çok iddia ediyorum olan tek yönlü bir sokak. Kalıtım, özel bir kompozisyon durumu için sadece sözdizimsel bir şekerdir.
weberc2

Açıkça uygulanan arayüzleri kullanarak kompozisyonu uygulayan bir dil kullanıldığında kompozisyon genellikle esnek değildir , çünkü bu arayüzlerin zaman içinde geriye dönük bir şekilde gelişmesine izin verilmemektedir. #jmtcw
MikeSchinkel

11

Belki de son birkaç ay içinde bunu söyleyen insanları fark ettiniz, ancak bundan daha uzun süredir iyi programcılar tarafından biliniyor. Ben kesinlikle yaklaşık on yıldır uygun olan yerlerde söylüyorum.

Konseptin amacı, kalıtımın üstünde büyük bir kavramsal yük olduğudur. Kalıtım kullanıyorsanız, her bir yöntem çağrısının içinde gizli bir gönderme olur. Derin bir miras ağacınız veya birden fazla gönderiminiz varsa (veya daha da kötüsü) varsa, belirli bir çağrıda belirli bir yöntemin nereye gönderileceğini bulmak, kraliyet PITA'sına dönüşebilir. Kod hakkında doğru muhakeme yapmayı daha karmaşık hale getirir ve hata ayıklamayı zorlaştırır.

Göstermek için basit bir örnek vereyim. Bir miras ağacının derinliklerinde, birinin yöntem olarak adlandırıldığını varsayalım foo. Sonra bir başkası gelir ve fooağacın tepesine ekler , ancak farklı bir şey yapıyor. (Bu durum çoklu mirasta daha yaygındır.) Artık kök sınıfta çalışan kişi belirsiz çocuk sınıfını kırmıştır ve muhtemelen bunu anlamamıştır. Ünite testleri ile% 100 kapsama sahip olabilirsiniz ve bu kırılmayı fark edemezsiniz; çünkü üstteki kişi çocuk sınıfını test etmeyi düşünmezdi ve çocuk sınıfının testleri üstte yaratılan yeni yöntemleri test etmeyi düşünmüyor. . (Kuşkusuz, bunu yakalayacak birim testleri yazmanın yolları vardır, ancak bu şekilde testleri kolayca yazamayacağınız durumlar da vardır.)

Aksine, kompozisyon kullandığınızda, her aramada, aramayı neye gönderdiğiniz genellikle daha açıktır. (Tamam, örneğin bağımlılık enjeksiyonuyla kontrolün tersini kullanıyorsanız, o zaman aramanın nereye gittiğini bulmak da sorunlu olabilir. Ancak, genellikle bunu anlamak daha kolaydır.) Bu, mantıklı olmayı kolaylaştırır. Bir bonus olarak, kompozisyon birbirinden ayrılmış metotlara yol açar. Yukarıdaki örnek orada olmamalıdır çünkü çocuk sınıfı belirsiz bir bileşene taşınır ve çağrının foobelirsiz bileşen için mi yoksa ana nesne için mi yapıldığına dair hiçbir soru yoktur .

Şimdi miras ve kompozisyonun iki farklı şeye hizmet eden iki farklı araç olduğu konusunda kesinlikle haklısın. Elbette kalıtım kavramsal yükü taşır, ancak iş için doğru araç olduğunda, kullanmaya çalışmaktan ve sizin için ne yaptığını elden yapmaya çalışmaktan daha az kavramsal yük taşır. Ne yaptıklarını bilen hiç kimse, asla miras almamanız gerektiğini söyleyemez. Ancak yapılacak doğru şey olduğundan emin olun.

Maalesef birçok geliştirici nesne yönelimli yazılımları öğrenir, kalıtım hakkında bilgi edinir ve ardından yeni baltalarını mümkün olduğunca sık kullanmaya gider. Bu, kompozisyonun doğru araç olduğu kalıtımı kullanmaya çalıştıkları anlamına gelir. Umarım zamanla daha iyi öğreneceklerdir, ancak sık sık bu, birkaç kaldırılmış uzuv vb.


3
Tamam, sanırım bu C ++ bakış açısından mantıklı. Bu hiç düşünmediğim bir şeydi, çünkü Delphi'de bir sorun değil, bu da çoğu zaman kullandığım şey. (Birden fazla devralma yoktur ve bir temel sınıfta bir yöntemle ve temel yöntemi geçersiz kılmayan türetilmiş bir sınıfta aynı ada sahip başka bir yönteminiz varsa, derleyici bir uyarı verir; bu tür bir sorunla.)
Mason Wheeler

1
@Mason: Nesne Pascal'ın (aka Delphi) And sürümü, kırılgan temel sınıf kalıtım problemi söz konusu olduğunda C ++ ve Java'dan üstündür. C ++ ve Java'nın tersine, devralınan bir sanal yöntemin aşırı yüklenmesi dolaylı değildir.
bit-twiddler

2
@ bit-twiddler, C ++ ve Java hakkında söyledikleriniz Smalltalk, Perl, Python, Ruby, JavaScript, Common Lisp, Objective-C ve OO desteği veren herhangi bir dil öğrendiğim hakkında söylenebilir. Bununla birlikte, googling C # 'nın Nesne Pascal'ın liderliğini takip ettiğini ileri sürüyor.
btilly

3
Çünkü Anders Hejlsberg, Borland'ın Object Pascal (aka Delphi) ve C # lezzetini tasarladı.
bit-twiddler

8

OO'nun yeni başlayanların ihtiyaç duymadıkları zaman kalıtımı kullanma eğiliminde olduğu gözlemine verilen tepki. Kalıtım kesinlikle kötü bir şey değildir, ancak aşırı kullanılabilir. Bir sınıf sadece diğerinden işlevselliğe ihtiyaç duyarsa, kompozisyon muhtemelen işe yarayacaktır. Diğer durumlarda, miras işe yarar ve kompozisyon çalışmaz.

Bir sınıftan miras almak birçok şeyi ima eder. Bir Derived'in bir Base tipi olduğu anlamına gelir ( kanyon detayları için Liskov İkame prensibine bakın). Bazlı korumalı üyelere ve üye fonksiyonlarına Türetilmiş erişim sağlar. Bu yakın bir ilişkidir, yani yüksek bağlaşmaya sahiptir ve birinde yapılan değişikliklerin diğerinde değişiklik yapması daha muhtemeldir.

Eşleştirme kötü bir şey. Programların anlaşılmasını ve değiştirilmesini zorlaştırır. Diğer şeyler eşit olmak üzere, her zaman daha az bağlantı içeren seçeneği seçmelisiniz.

Bu nedenle, eğer bir kompozisyon ya da miras işi etkin bir şekilde yapacaksa, kompozisyonu seçin, çünkü daha düşük birleşmedir. Eğer kompozisyon işi etkili bir şekilde yapmazsa ve miras alırsa, miras almayı seçmelisin, çünkü yapmak zorundasın.


"Diğer durumlarda, miras işe yarayacak ve kompozisyon çalışmayacak." Ne zaman? Kalıtım, kompozisyon ve arayüz polimorfizmi kullanılarak modellenebilir, bu yüzden kompozisyonun işe yaramayacağı herhangi bir koşul varsa, şaşırırım.
weberc2

8

İşte benim iki kuruş (zaten yükseltilmiş tüm mükemmel noktaların ötesinde):

IMHO, Programcıların çoğunun gerçekten miras almadığı ve kısmen bu kavramın nasıl öğretildiğinin bir sonucu olarak, aşırıya kaçma gerçeği ortaya çıkıyor. Bu kavram, nasıl doğru yapmaları gerektiğini öğretmeye odaklanmak yerine onları aşırıya kaçmalarını engellemeye çalışmanın bir yolu olarak var.

Öğretmek veya mentorluk yapmak için zaman harcayan herkes, özellikle diğer paradigmalarda tecrübesi olan yeni geliştiricilerle bunun ne olduğunu bilir:

Bu geliştiriciler başlangıçta kalıtımın bu korkutucu kavram olduğunu düşünüyor. Bu yüzden ara yüzleri örtüşen tiplerle (ör. Ortak alt tiplendirme olmadan aynı belirlenmiş davranış) ve ortak işlevsellik parçalarını uygulamak için küreselleştiler.

Sonra (çoğu zaman aşırı öğretmenin bir sonucu olarak), kalıtımın faydalarını öğrenir, ancak çoğu zaman yeniden kullanılması için hepsini yakala çözümü olarak öğretilir. Herhangi bir ortak davranışın kalıtım yoluyla paylaşılması gerektiğine dair bir algıyla son bulurlar. Bunun nedeni, odaklamanın alt türleme yapmaktan ziyade uygulama kalıtımı üzerine olmasıdır.

Vakaların% 80'inde bu yeterince iyi. Fakat diğer% 20 ise sorunun başladığı yer. Yeniden yazmaktan kaçınmak ve uygulama paylaşımından faydalandıklarından emin olmak için, temel soyutlamaları yerine amaçlanan uygulama etrafında hiyerarşilerini tasarlamaya başlarlar. "Yığın çift bağlantılı listeden miras kalmıştır" buna güzel bir örnektir.

Öğretmenlerin çoğu, bu noktada arayüz kavramını tanıtmakta ısrar etmemektedir, çünkü bu başka bir kavramdır veya (C ++ 'da), bu aşamada öğretilmeyen soyut sınıfları ve çoklu kalıtım kullanarak onları taklit etmeniz gerektiği için. Java'da, birçok öğretmen "çoklu kalıtım yok" veya "çoklu kalıtım kötüdür" ifadelerini arayüzlerin öneminden ayırmaz.

Tüm bunlar, uygulama mirası ile gereksiz kod yazmak zorunda olmamanın güzelliğini o kadar çok şey öğrenmiş olduğumuzla birleşiyor: tonlarca basit delegasyon kodu doğal değil. Bu yüzden kompozisyon dağınık görünüyor, bu yüzden yeni programcıları tekrar kullanmaya zorlamak için bu kurallara ihtiyacımız var.


Bu eğitimin gerçek bir parçası. Örneğin,% 20 geri kalanını almak için daha yüksek kurslar yapmanız gerekir, ancak siz öğrenci olarak, sadece temel ve belki de ara kursları öğrettiniz. Sonunda, iyi bir şekilde öğretildiğinizi hissediyorsunuz çünkü derslerinizi iyi yaptınız (ve sadece merdivenin üzerinde bir pin göremiyorum). Bu sadece gerçekliğin bir parçası ve en iyisi, kodlayıcılara saldırmak değil, yan etkilerini anlamak.
Bağımsız

8

Yorumlardan birinde Mason, bir gün zararlı olduğu düşünülen Miras hakkında konuşacağımızı söyledi .

Umarım.

Kalıtım problemi bir kerede basittir ve ölümcül bir kavramın bir fonksiyonelliğe sahip olması gerektiği fikrine saygı duymaz.

Çoğu OO dilinde, bir temel sınıftan miras alırken:

  • arayüzünden devralır
  • Uygulamasından devralmak (hem veri hem de yöntem)

Ve işte sorun haline geldi.

Bu değil 00-dil çoğunlukla onunla sıkışmış olsa sadece bir yaklaşım. Neyse ki arayüzlerde / soyut sınıflarda var.

Ayrıca, aksi takdirde yapmanın kolay olmayışı, büyük ölçüde kullanılmasına katkıda bulunur: açıkçası, bunu bilseniz bile, bir arabirimden miras alırsınız ve temel sınıfı yöntem çağrıları delegasyonunu yaparak kompozisyona katıştırır mısınız? Yine de daha iyi olurdu, eğer aniden arayüzde yeni bir yöntem ortaya çıkarsa ve onu nasıl uygulayacağınızı bilinçli olarak seçmek zorunda kalırsanız bile uyarılırsınız.

Bir sayaç noktası olarak, Haskellyalnızca Liskov Prensibi'ni saf arayüzlerden (kavramlar denir) "türetirken" kullanmaya izin verin (1). Mevcut bir sınıftan türetemezsiniz, yalnızca kompozisyon verilerini yerleştirmenize izin verir.

(1) kavramlar bir uygulama için makul bir varsayılan sağlayabilir, ancak hiçbir veriye sahip olmadıkları için, bu varsayılan sadece konsept tarafından önerilen diğer yöntemler veya sabitler olarak tanımlanabilir.


7

Basit cevap şudur: miras, kompozisyondan daha fazla birliğe sahiptir. İki seçenek, eşdeğer niteliklere sahip iki seçenek göz önüne alındığında, daha az bağlı olanı seçin.


2
Ama asıl mesele bu. Onlar konum değil "aksi eşdeğer." Kalıtım, OOP kullanımının tamamı olan Liskov ikame ve polimorfizmini sağlar. Kompozisyon değil.
Mason Wheeler

4
Polimorfizm / LSP, OOP'nin "bütün noktası" değil, bir özelliktir. Kapsülleme, soyutlamalar vb. Vardır. Miras, "bir" ilişkidir, anlaşma modellerinin "bir" ilişkiye sahip olduğunu belirtir.
Steve

@Steve: Veri yapıları ve prosedürleri / fonksiyonlarının oluşturulmasını destekleyen herhangi bir paradigmada soyutlamalar ve kapsülleme yapabilirsiniz. Ancak polimorfizm (özellikle bu bağlamda gönderilen sanal yönteme gönderme yapar) ve Liskov ikamesi, nesne yönelimli programlamaya özgüdür. Demek istediğim bu.
Mason Wheeler

3
@Mason: Kılavuz, “mirasa ilişkin kompozisyonu desteklemektir”. Bu, hiçbir şekilde miras almamak ve hatta kalmamak anlamına gelmez. Bütün diğer şeyler eşit olduğunda kompozisyonu seçtiğini söylüyor. Ancak mirasa ihtiyacınız varsa kullanın!
Jeffrey Faust

7

Bence bu tür bir tavsiye "uçmayı tercih et" demeye benziyor. Yani, uçakların otomobillere göre her türlü avantajı var, ancak bu kesin bir karmaşıklıkla geliyor. Bu yüzden eğer birçok insan şehir merkezinden banliyölere uçmaya çalışırsa, gerçekten, gerçekten duymaları gereken tavsiye , uçmaları gerekmediğidir ve aslında, uçmak onu uzun vadede daha karmaşık hale getirecektir. Kısa vadede serin / verimli / kolay gibi görünse de. Ne zaman Oysa do uçmak gerekir, genellikle belirgin olması gerekiyor.

Aynı şekilde, miras, kompozisyonun yapamayacağı şeyleri yapabilir, ancak ihtiyacınız olduğunda değil, ihtiyacınız olduğunda bunu kullanmalısınız. Öyleyse, istemediğiniz zaman mirasa ihtiyacınız olduğunu varsaymaya hiç hevesli değilseniz, “kompozisyonu tercih etme” tavsiyesine ihtiyacınız yoktur. Ama pek çok insan yapmak ve bunu bu tavsiyeye ihtiyacım var.

Gerçekten mirasa ihtiyaç duyduğunuzda, bunun bariz olduğu ve sonra kullanmanız gerektiği açık olmalı.

Ayrıca, Steven Lowe'ın cevabı. Gerçekten, gerçekten bu.


1
Ben senin benzetme gibi
barrylloyd

2

Kalıtım doğal olarak kötü değildir ve kompozisyon doğal olarak iyi değildir. Bunlar sadece bir OO programcısının yazılım tasarlamak için kullanabileceği araçlardır.

Bir sınıfa baktığınızda, kesinlikle gerekenden fazlasını yapıyor mu ( SRP )? Gereksiz bir şekilde ( DRY ) çoğaltma işlevi mi , yoksa diğer sınıfların ( Feature Envy ) özellikleri veya yöntemleriyle aşırı derecede ilgileniyor mu? Eğer sınıf bütün bu kavramları ihlal ediyorsa (ve muhtemelen daha fazlası), bir Tanrı Sınıfı olmaya çalışıyor mu ? Bunlar, hiçbiri bir miras problemi olmayan, ancak tasarımı hızlıca ortaya çıkarabilecek, ancak polimorfizmin uygulandığı yerlerde büyük baş ağrıları ve kırılgan bağımlılıklar yaratabilen bir takım problemlerdir.

Sorunun kökü, kalıtım hakkında daha az bir anlayış eksikliği olabilir ve tasarım açısından zayıf tercihlerden biri olabilir veya belki de Tek Sorumluluk Prensibi'ne uymayan sınıflarla ilgili "kod kokularını" tanımıyor olabilir . Polimorfizm ve Liskov Değiştirmenin kompozisyon lehine atılmasına gerek yoktur. Polimorfizmin kendisi mirasa güvenmeksizin uygulanabilir, bunlar tamamen ücretsiz kavramlardır. Dikkatlice uygulanırsa. İşin püf noktası, kodunuzu basit ve temiz tutmayı ve sağlam bir sistem tasarımı oluşturmak için oluşturmanız gereken sınıfların sayısı konusunda fazla endişelenmekten vazgeçmemeyi hedeflemektir.

Mirastan yana bir kompozisyon lehine olana gelince, bu gerçekten çözülen problem açısından en anlamlı olan tasarım öğelerinin düşünceli bir şekilde uygulanması durumudur. Eğer yoksa ihtiyaç davranışı miras, o zaman muhtemelen kompozisyon uyumsuzluklar ve başlıca üstlenmeden çabaları sonradan önlemek için yardımcı olacaktır olmamalıdır olarak. Öte yandan, çoğaltmanın benzer sınıfların bir grubuna odaklanacağı şekilde çok sayıda kod tekrarladığınızı fark ederseniz, ortak bir ata oluşturmanın aynı çağrı ve sınıfların sayısını azaltmaya yardımcı olabileceği anlamına gelir. Her sınıf arasında tekrar etmeniz gerekebilir. Bu nedenle, kompozisyonu tercih ediyorsunuz, ancak mirasın asla geçerli olmadığını varsaymıyorsunuz.


-1

Asıl alıntı, sanırım, bölümlerden birinin adı olan Joshua Bloch'un "Etkin Java'sından" geliyor. Kalıtımın bir paket içinde ve bir sınıfın uzatma için özel olarak tasarlandığı ve belgelendiği her yerde güvenli olduğunu iddia eder. Diğerlerinin de belirttiği gibi, mirasın kapsüllemeyi bozduğunu, çünkü bir alt sınıfın, üst sınıfının uygulama detaylarına bağlı olduğunu iddia ediyor. Bu, kırılganlığa yol açtığını söylüyor.

Her ne kadar bahsetmese de, bana öyle geliyor ki, Java'daki tek miras, kompozisyonun size mirastan çok daha fazla esneklik kazandırdığı anlamına geliyor.

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.