Moninkertainen periytyminen on ominaisuus, jota osa olio- ohjelmointikieliä tukee , kun luokassa voi olla useampi kuin yksi superluokka (suora emoluokka), rajapinnat tukevat useiden ohjelmointikielien moniperiytymistä. Tämä käsite on "yksinkertaisen (tai yksittäisen) perinnön " ( englanniksi single inheritance ) laajennus , jossa luokka voi periä vain yhdestä superluokasta.
Useita perintöä tukevia kieliä ovat: Io , Eiffel , C++ , Dylan , Python , jotkin JavaScript -luokan toteutukset (esim. dojo .declare ), Perl 6 , Curl , Common Lisp ( CLOSin ansiosta ), OCaml , Tcl ( Incrementalin ansiosta ). Tcl ) [1] sekä Object REXX ( mixin-luokkien käytön vuoksi ).
Usein periytymisen ansiosta luokka voi periä toimintoja monista muista luokista, kuten luokka StudentMusicianvoi periä luokasta class Person, class Musicianja class Worker, jotka voidaan lyhentää seuraavasti:
StudentMusician : Person, Musician, Worker.Epävarmuus moninkertaisessa periytymisessä, kuten yllä olevassa esimerkissä, tapahtuu, jos esimerkiksi luokka Musicianperii luokista Personja Worker, ja luokka Workerpuolestaan perii Person; samanlaista tilannetta kutsutaan vinoneliön muotoiseksi periytymiseksi . Siten saamme seuraavat säännöt:
Työntekijä : Henkilö Muusikko : Henkilö, Työntekijä OpiskelijaMuusikko : Henkilö, Muusikko, TyöntekijäJos kääntäjä tarkastelee StudentMusician-luokkaa, sen on tiedettävä, pitäisikö luokkien ominaisuuksia yhdistää vai erillään. Esimerkiksi olisi loogista liittää StudentMusician-luokkaan Person-luokan "Ikä" (ikä). Henkilön ikä ei muutu, jos pidät häntä Henkilönä (henkilönä), Työntekijänä (työntekijänä) tai Muusikkona (muusikkona). Olisi kuitenkin aivan loogista erottaa "Nimi"-ominaisuus henkilö- ja muusikko-luokissa, jos he käyttävät taiteilijanimeä, joka poikkeaa heidän oikeasta nimestään. Join- ja split-vaihtoehdot ovat täysin voimassa jokaisessa omassa kontekstissaan, ja vain ohjelmoija tietää, mikä vaihtoehto on oikea suunniteltavalle luokalle.
Kielillä on useita tapoja käsitellä tällaisia sisäkkäisiä perintöongelmia, esimerkiksi:
Smalltalk , C# , Objective-C , Java , Nemerle ja PHP eivät salli moninkertaista periytymistä, mikä välttää monia epävarmuustekijöitä. Ne antavat kuitenkin Smalltalkin lisäksi luokat toteuttaa useita rajapintoja . Lisäksi PHP ja Ruby antavat sinun emuloida useita perintöjä käyttämällä mixinejä (piirteitä PHP:ssä ja mixins Rubyssa), jotka, kuten käyttöliittymät, eivät ole täysimittaisia luokkia. Monien rajapintojen periytymisen ansiosta voit laajentaa rajoitettuja ominaisuuksia.
Moninkertaista periytymistä on kritisoitu seuraavista ongelmista joissakin kielissä, erityisesti C++:ssa:
C++/Java-tyylisten konstruktorien moninkertainen periytyminen pahentaa rakentajien periytymis- ja konstruktorisekvenssien ongelmaa, mikä aiheuttaa ylläpidettävyys- ja laajennettavuusongelmia näissä kielissä. Periytyssuhteissa olevia objekteja, joilla on merkittävästi erilaisia rakennusmenetelmiä, on melko vaikea toteuttaa konstruktorisekvenssiparadigmassa.
On kuitenkin olemassa kieliä, jotka käsittelevät näitä teknisiä asioita (esim. Eiffel ).
On olemassa mielipide, että moniperintö on väärä käsite, joka syntyy väärästä analyysistä ja suunnittelusta. Erityisesti seuraava suunnitteluvaihtoehto pätee yllä olevaan esimerkkiin. Henkilö-luokka sisältää yhden tai useamman Ammatti-luokan objektin. Opiskelija- ja muusikko-luokat periytyvät ammatista. Siten StudentMusician edustaa luokan Person objektia, joka sisältää luokan Opiskelija ja Muusikko objekteja. Muodollisesti moninkertainen periytyminen voidaan käänteistä ottamalla käyttöön luokka, joka on "metaluokka" luokista, joista moninkertainen periytyminen tapahtuu. Yllä olevassa esimerkissä tällainen metaluokka on ammatti - ammatti.