Multiple inheritance

Tags:    .net
Skrevet af Bruger #285 @ 23.01.2007
I C# er det ikke muligt at nedarve fra mere end maksimalt én klasse; dvs. multiple inheritance (MI) ikke er muligt. Man kan argumentere både for og imod, om det i et fornuftigt vil være nødvendigt, men man kommer ikke uden om, at det rent teoretisk burde være muligt. Og hvor skulle man rent praktisk bruge det; hvis jeg siger husbåd, hvad siger du så (ja ja, men du ved, hvad jeg mener)?

Det at en klasse vil kunne have mere end én superklasse, kan skabe mange problemer. Hvad nu hvis begge superklasser har en metode ved sammen navn? Hvilken en skal så benyttes? I et programmeringssprog som Eiffel, der understøtter MI, er det fx muligt at omdøbe, redefinere m.fl. nedarvede metoder således der ikke kommer konflikter.

Jeg nævte jo, at det ikke var muligt i C#, men man kan faktisk godt, hvis man virkelig vil - omend det ikke er "ren" MI:
Fold kodeboks ind/udKode 


Som det ses her, laver man et "fælles" interface, der egentlig skal fungere som et form for kunstig superklasse, og klassen A så er et hængeled, der rent faktisk er klassen, der implementerer metoderne. For at få nedarvningen til at virke, nedarver man så fra superklassen (der egentlig er et interface), og benytter implementeringen stillet til rådighed af hjælpeklassen A. På den måde er både MI og A af typen IAClass, og MI er ovenikøbet også af typen Base. Så kan man fx i funktioner angive et parameter til værende af typen IAClass, og så kan både A og MI objekter benyttes!

Lidt "fusket", men denne omvej gør det rent faktisk muligt!


Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (11)

User
Bruger #285 @ 25.01.07 10:00
Hej. Jeg kan se mine nye artikler bliver stemt til 1 og 2. Det er selvfølgelig helt okay, men I må hjertens gerne lige knytte en kommentar til hvorfor, således jeg har mulighed for at ændre det i fremtiden. Hvis I vil være anonyme, kan I bare sende det til KasperTSW og sige det, så kan han vidregive det til mig uden jeres navn. Men altså: jeg har intet imod lave bedømmelser, jeg vil bare gerne have en mulighed for at kunne gøre det bedre fremover.
User
Bruger #2967 @ 26.01.07 14:46
Det her skulle bare have været under interfaces...
User
Bruger #285 @ 26.01.07 14:53
Ja, det vil jeg både sige ja og nej til, da interfaces blot løser det generelle problem med MI; det kunne lige så godt have været en anden teknik. Men ja, da det - umiddelbart - er den mest oplagte måde i C#, bure det måske have været derunder.
User
Bruger #2193 @ 08.02.07 12:15
Hvem godkendte denne artikel?
Den har så godt som intet med arv at gøre.
Titlen er misvisende og forklaringen direkte forkert.

Jeg forventer man forstår det man snakker om inden man skriver en artikel.
Troede egentligt også at de som godkender artikler kræver det samme.
User
Bruger #285 @ 09.02.07 17:39
Jonathan: Vil du venligst uddybe din kritik? Artiklen bliver indledt med en kort forklaring af, at MI i C# ikke er mulig, og derefter hvordan det "kunstigt" kan laves vha. implementering af interfaces. Så jeg forstå ikke helt din kritik (jeg siger ikke, at den ikke er berittiget, men det skal begrundes dybere - og en påstand om at hverken jeg eller artikeljuryen forstå stoffet er måske lige lidt i overkanten, synes jeg - især når ikke det er begrundet). Jeg er meget åben for positiv kritik, men ubegrundet kritik er i min verden ikke konstruktivt - sorry. Så kom med nogle argumenter, så jeg kan lære noget - så vil jeg være glad :-)
User
Bruger #2193 @ 12.02.07 08:05
Mitkl-dk: Hvis jeg skulle forklare dig hvad problemets fulde omfang er, så skulle jeg skrive en hel artikel. Men det er dig der har valgt at skrive en artikel, og ikke mig.

Hvis du stiller dig helt uforstående overfor kritikken, så er det fordi du absolut ikke ved hvad arv og brug af interfaces handler om.
Det kan ikke repareres med 3 sætninger.

At arve betyder at en klasse bliver en udbygning af sin super-klasse. At den så at sige arver super-klassens navn (når man f.eks. caster den til super-klassen), men også send funktioner arver man.

At implementere et interface betyder at man binder sin klasse til at opfylde de metode-signaturer som det pågældende interface definerer.
Ens klasse kan godt nok castes til interface klassen, men arver ikke noget fra interfacet.
At man kan implementere mange interfaces gør at man i nogen forstand kan benytte interfaces istedet for MI, specielt hvis ens grund til MI hovedsagligt er at kunne caste til bestemte "klasser" (også interfaces her) og ikke en object orienteres arve struktur. Ofte en god ide hvis man er ved at bygge et subsystem og har behov for Facade og Parameter design, eller hvis man vil dele signatur men ikke kode med andre subsystemer.

Det er simple ting, arv og interface, men at mixe det sammen som du gør højner ikke forståelsen for læseren, og tyder på at du enten ikke helt selv har styr på forskellene eller også bare har skrevet en sloppy artikel.

Med andre ord kritiserer jeg artikels titel, artiklens eksempel og dens indhold samt forklaring.
User
Bruger #285 @ 13.02.07 10:47
Jonathan: Jo, jeg er skam udemærket klar over, hvad det er. Det er muligt, at det i artiklen ikke er forklaret tydeligt nok (altså der mangler givetvis en længere introduktion til emnet) - den kritik tager jeg til mig. Men jeg synes der er et stykke vej fra at savne en introduktion på et begynderniveau om OOP (i en artikel beregnet til "lettere øvede") til at komme med påstande om uvidenhed. Og du behøver mig ikke forklare begreberne, jeg er skam godt klar over dem (faktisk vil jeg tillade mig at komme med den bemærkning, at rent konceptuelt så er arv ikke kun udvidning af superklassen - det kan med lige ret ske pga. specialisering af superklassen). Så jeg vedkender, at der muligvis mangler en introduktion (men så ville artiklen måske i stedet henvende sig til begyndere) - dog må jeg nok indrømme, at jeg er en smule harm over at blive beskyldt for at være uvidende :-) Beklager :-)
User
Bruger #2193 @ 14.02.07 07:52
Mitkl-dk: Jeg beklager at jeg har gjort dig harm!
Det var ikke meningen, men jeg må samtidigt indrømme at jeg nok gik ud fra at det var fordi du ikke anede forskellen og ikke helt havde forstået tingene rigtigt til bunds at du skrev den artikel som du gjorde.
Beklager hvis jeg tog fejl, men så er jeg tilbage til ikke helt at forstå hvorfor du vil have at jeg forklarer mig (er det ikke ret indlysende hvis du virkelig har forstået hvad arv er og hvad interfaces er?), og heller ikke hvorfor du skrev den artikel som du gjorde.

Men lad nu det ligge, og igen jeg beklager jeg gjorde dig harm, men kan man ikke tage kritik så hjælper det ikke at forsvare sig bittert, og så skulle man måske overveje at undlade at skrive en artikel (og det emne om ikke andet)?

Ydermere gik min originale kritik mindst lige så meget på artikel juryen, for det er jo dem der har ansvaret for indholdet i en artikel. Hvad skulle de ellers være der for?

Sat på spidsen, så er der enten noget galt med artikel juryens opfattelse af arv og interfaces, eller også er der noget galt med min.
User
Bruger #285 @ 14.02.07 10:17
Jonathan:
He he - jeg ved ikke om du skal beklage, du har gjort det. Og jeg kan sagtens tage kritik, hvis den er konstruktiv :-) Men måske jeg ikke tog den helt, som den var ment - og det beklager jeg naturligvis. Jeg ved udemærket at du har styr på, hvad du snakker om - men jeg skriver ikke en artikel uden at vide, hvad jeg snakker om (det er muligt artiklen som her er tynd - og jeg vil give dig ret i, at netop den her er en smule tvetydig). Samtidig vil jeg stadig holde fast i, at hvis man kender OOP-principperne, så vil man udemærket forstå denne artikel, og så vil man opfatte den som en lille sjov twist af, hvordan man kan få en MI-lignende "mekanisme" i C#.

Egentlig ligger vores differentierede opfattelser nok i, hvad vi forstår ved sætningen "Jeg nævte jo, at det ikke var muligt i C#, men man kan faktisk godt, hvis man virkelig vil - omend det ikke er "ren" MI" i aftiklen og i det hele taget er formålet med artiklen måske en smule uklart. Måske jeg skylder en lille artikel til at gøre det godt igen. Og for så lige at bruge dig, nu jeg har dig, hvad ville du så synes, ville være passende?

En brainstorm over indhold:
1) OOP-principper (nedarvning, indkapsling osv.)
2) klasser/interfaces (superklasser/subklasser/implementering af interfaces)
3) C# implementation (begrænsninger som fx MI - og hvorfor de er der)
4) C#'s kort sat i perspektiv til andre (fx Eiffel, hvor MI jo er muligt)
User
Bruger #2193 @ 14.02.07 11:32
Mitkl-dk: Du skylder ikke noget noget!

Men hvis der er frit valg fra alle hylder, så kunne nr 3 være interessant.
:)

Den største forskel i vores opfattelse er nok at jeg mener at Interface implementering intet har at gøre med arv, hverken arv fra en enkelt superklasse eller MI.

Som jeg tror jeg har nævnt mindst en enkelt gang, så kan det godt være at MI og Interfaces lugter lidt af de samme muligheder hvis man udelukkende fokuserer på "casting" mulighederne, men selv med det i tanke mener jeg stadig at MI og Interfaces intet har med hinanden at gøre - overhovedet!

Jeg må hellere stoppe her inden jeg kommer for godt igang igen. :)
User
Bruger #285 @ 14.02.07 13:07
Både og - den stribe artikler er lidt hurtige, så synes egentlig jeg skylder en ordentlig én :-)

Nej, jamen jeg er helt enig med dig! Interfaces HAR vitterligt intet med arv at gøre - netop fordi de blot "dikterer" uden at "gøre noget", hvis man sådan skal gøre princippet tydeligt, men de kan bruges som et værktøj/hack til at opnå en MI-lignende effekt.

Så jeg tror nu vi er enige - det er bare skrevet for dårligt i artiklen.
Du skal være logget ind for at skrive en kommentar.
t