Multipelt arv
Multipelarv är en egenskap som stöds av delar av objektorienterade programmeringsspråk , när en klass kan ha mer än en superklass (direkt överordnad klass), stöder gränssnitt multipelt arv i många programmeringsspråk. Detta koncept är en förlängning av "enkelt (eller enstaka) arv " ( Engelska enkelarv ), där en klass bara kan ärva från en superklass.
Språk som stöder flera arv inkluderar: Io , Eiffel , C++ , Dylan , Python , vissa JavaScript -klassimplementeringar (t.ex. dojo .declare ), Perl 6 , Curl , Common Lisp (tack vare CLOS ), OCaml , Tcl (tack vare Incremental ) Tcl ) [1] , såväl som Object REXX (på grund av användningen av mixin-klasser ).
Översikt
Multipelt arv tillåter en klass att ärva funktionalitet från många andra klasser, till exempel en klass StudentMusiciankan ärva från klass Person, klass Musicianoch klass Worker, som kan förkortas som:
StudentMusician : Person, Musician, Worker.
Osäkerhet vid multipelarv, som i exemplet ovan, uppstår om till exempel en klass Musicianärver från klasser Personoch Worker, och klassen Workeri sin tur ärver från Person; en liknande situation kallas diamantformad arv . Därför får vi följande regler:
Arbetare : Person
Musiker : Person, Arbetare
StudentMusiker : Person, Musiker, Arbetare
Om kompilatorn tittar på StudentMusician-klassen måste den veta om funktionerna i klasserna ska kombineras eller vara separata. Till exempel skulle det vara logiskt att koppla "Ålder" (ålder) för klassen Person till klassen StudentMusician. En persons ålder ändras inte om du betraktar honom som person (person), arbetare (arbetare) eller musiker (musiker). Det skulle dock vara ganska logiskt att separera egenskapen "Namn" i klasserna Person och Musiker om de använder ett artistnamn som skiljer sig från deras riktiga namn. Alternativen för join och split är helt giltiga för var och en av deras egna sammanhang, och bara programmeraren vet vilket alternativ som är korrekt för klassen som designas.
Språk har olika sätt att hantera sådana kapslade arvsproblem, till exempel:
- Eiffel ger programmeraren möjligheten att uttryckligen kombinera eller dela ärvda medlemmar från superklasser. Eiffel kommer automatiskt att slå samman element om de har samma namn och implementering. Klassförfattaren har möjlighet att byta namn på ärvda medlemmar för att skilja dem åt. Dessutom tillåter Eiffel dig att uttryckligen återärvaA: B, B .
- C++ kräver att programmeraren specificerar vilken överordnad klassmedlem som ska användas, dvs "Worker::Person.Age". C++ stöder inte uttryckligen repeterbart arv eftersom det inte finns något sätt att avgöra vilken superklass som ska användas (se kritik ). C++ tillåter också skapandet av en enda instans av en multipelklass på grund av den virtuella arvsmekanismen (till exempel " Worker::Person" och " Musician::Person" kommer att referera till samma objekt).
- Perl använder en lista över klasser att ärva från i den ordningen. Kompilatorn använder den första metoden den hittar vid djupsökning i listan över superklasser eller använder C3-linearisering av klasshierarkin. Olika tillägg tillhandahåller alternativa klasssammansättningsscheman.
- Python har syntaktisk stöd för multipelt arv, och ordningen på basklasserna bestäms av C3-lineariseringsalgoritmen [2] .
- Common Lisp Object System ger programmeraren full kontroll över kombinationsmetoderna, och om detta inte räcker, ger Metaobject Protocol (Metaobject Protocol) programmeraren möjligheten att modifiera arv, dynamisk hantering , klassimplementering och andra interna mekanismer utan rädsla för att påverka systemets stabilitet.
- Logtalk stöder både gränssnitt och implementering av multi-arv genom att tillhandahålla en aliasmetoddeklaration som stöder både byte av namn och åtkomst till metoder som kanske inte är tillgängliga på grund av konfliktlösningsmekanismen.
- Curl tillåter endast klasser som uttryckligen är markerade som återärvbara . Tillgängliga klasser måste definiera en sekundär konstruktor för varje normal klasskonstruktör . Den vanliga konstruktorn anropas först, den tillgängliga klassstatusen initieras av underklasskonstruktorn och den sekundära konstruktorn anropas för alla andra underklasser.
- Ocaml väljer den sista matchningsdefinitionen i klassarvslistan för att bestämma implementeringsmetoden som ska användas i händelse av osäkerhet. För att åsidosätta standardbeteendet, tillhandahåll helt enkelt en metod som ska anropas när du definierar den föredragna klassen.
- Tcl tillåter förekomsten av flera överordnade klasser - deras sekvens påverkar upplösningen av namnen på klassmedlemmar. [3]
- Delphi sedan version 2007 tillåter dig att delvis implementera multipla arv med hjälp av klasshjälpare (Class Helpers) .
Smalltalk , C# , Objective-C , Java , Nemerle och PHP tillåter inte multipelt arv, vilket undviker många osäkerheter. Men de, förutom Smalltalk, tillåter klasser att implementera flera gränssnitt . Dessutom låter PHP och Ruby dig emulera multipla arv genom användning av mixins (egenskaper i PHP och mixins i Ruby), som, liksom gränssnitt, inte är fullfjädrade klasser. Flera arv av gränssnitt gör att du kan utöka begränsade möjligheter.
Kritik
Multipelt arv har kritiserats för följande problem på vissa språk, särskilt C++:
- semantisk tvetydighet representeras ofta kollektivt som Diamantproblemet [4] .
- det finns ingen möjlighet till direkt multipel arv från en klass.
- arvsordningen ändrar klassens semantik. Konstruktören av barnklassen anropar de närmaste föräldrarnas konstruktörer, och de i sin tur anropar konstruktören av morföräldern. Grandparent-objektet finns dock i en enda instans och det kan inte konstrueras två gånger, så att anropa grandparent-konstruktorn endast av konstruktorn för den första överordnade klassen i arvslistan fungerar.
Multipelt arv i språk med konstruktörer i C++/Java-stil förvärrar problemet med konstruktörsarv och konstruktorsekvenser, vilket skapar problem med underhåll och utökbarhet i dessa språk. Objekt i arvsrelationer med väsentligt olika konstruktionsmetoder är ganska svåra att implementera inom konstruktorsekvensparadigmet.
Det finns dock språk som hanterar dessa teknikaliteter (t.ex. Eiffel ).
Det finns en åsikt att multipelt arv är ett felaktigt koncept, genererat av felaktig analys och design. I synnerhet gäller följande designalternativ för exemplet ovan. Klassen Person inkluderar ett eller flera objekt av klassen Profession. Student- och musikerklasserna ärver från Profession. Således kommer StudentMusician att representeras av ett objekt av klassen Person som innehåller objekt av klassen Student och Musiker. Formellt kan multipelt arv omvändas genom att introducera en klass som är en "metaklass" av de klasser från vilka multipelt arv ska ske. I exemplet ovan är en sådan metaklass Profession - ett yrke.
Anteckningar
- ↑ Tcl Advocacy . Hämtad 2 december 2009. Arkiverad från originalet 22 september 2010. (obestämd)
- ↑ David M. Beazley. Python Essential Reference . — 4:e upplagan. - Addison-Wesley Professional, 2009. - S. 119 -122. — 717 sid. — ISBN 978-0672329784 .
- ↑ Tcl Manual: klass . Hämtad 2 december 2009. Arkiverad från originalet 4 april 2009. (obestämd)
- ↑ Egenskaper: Sammansättbara enheter av beteende . Hämtad 2 december 2009. Arkiverad från originalet 9 augusti 2017. (obestämd)
Länkar
Litteratur