Avatar billede scorp-d Nybegynder
08. juni 2011 - 09:32 Der er 6 kommentarer og
1 løsning

Pattern til "nedarvning" af flere klasser samtidig

Hej,

Hvis jeg har 2 abstrakte klasser, der indeholder noget logik som ikke nødvendigvis har noget tilfælles, hvordan samler jeg så de 2 abstrakte klassers metoder i én fælles klasse, men hvor det stadig er muligt at udbygge de abstrakte klasser ved at extende og tilføje metoder, og benytte de nye metoder i den fælles klasse.


Jeg kunne selvfølgelig blot have 2 klasser som extender de abstrakte klasser, og havde dem som variabler i den fælles klasse.

Men hvis andre klasser så skal tilgå de 2 klassers metoder igennem den fælles klasse, så skal den have metoder der kalder alle deres metoder.

Hvilket vil sige, at hvis slutbrugeren tilføjer metoder i de klasse der extender de abstrakte klasser, skal de også tilføje metodekald i den klasse der extender den fælles klasse, samt overstyre dens initialisering af de 2 klasser.


På forhånd tak.



Lidt ekstra info:
Jeg arbejder på et "framework", i et sprog som er nært beslægtede med C#, og det er derfor nødvendigt at slutbrugerne(som så er udviklere) skal rette så lidt som muligt i vores framework, da deres kode derved kan blive ødelagt når vi kommer med nye versioner.

Indtil videre benytter vi os primært af opsplitning i klasser(næsten til grænsen af det ekstreme) og erklære dem som abstrakte, så skal brugerne blot extende, og evt. tilføje ekstra logik.

Når vi så kommer med nye versioner, røre det meget sjældent ved deres implementering af løsningen.
Avatar billede aaberg Nybegynder
08. juni 2011 - 10:06 #1
Hvis jeg forstår dig rigtigt, kan du sikkert løse dit problem ved at bruge extension methods.
http://msdn.microsoft.com/en-us/library/bb383977.aspx

Det er denne metode der bliver brugt i LINQ. Du kan eksempeltvis kalde Select() metoden på alle klasser der nedarver fra IEnumerable. IEnumerable er et interface, og har derfor ingen metoder. Metoden kommer "ude fra" som en extension.

I dit eksempel: Du har noget funktionalitet, som dine kunders klasser skal kunne bruge. Og de skal gerne kunne bruge funktionalitet fra flere forskellige "klasser" samtiddig. I stedet for at bruge abstrakte klasser, kan du bruge interfaces. En klasse kan nedarve fra mange interfaces. Til disse interfaces laver du et antal extension metods. Så får kundens klasse funktionalitet fra begge extension klasse samtiddig. Og når du tilføjer extensions i fremtiden, behøver kunden ikke at gøre noget, da den nye funktionalitet automatisk er tilknyttet interfacene han nedarver fra.
Avatar billede scorp-d Nybegynder
08. juni 2011 - 10:29 #2
Ser rigtig spændende ud, og er noget jeg vil prøve at lege med i min fritid.

Desværre har det sprog jeg benytter ikke fået implementeret det endnu.


Også lidt det jeg forventede, og derfor et generelt pattern, eller BP-måde at gøre det på ville være super...
Avatar billede arne_v Ekspert
09. juni 2011 - 05:01 #3
1) grundliggende er designet forkert - hvis de klasser ikke har noget med hinanden at goere, saa er det ikke god OO at lave en enkelt klasse med den samlede funktionalitet

2) det grundliggende design maa jo noedvendigvis vaere at:
* klassen S har et antal members af typerne C1..Cn
* S har alle metoder i C1..Cn og forwarder kald til de rigtige metoder i C1..Cn instanserne
* S instantieres enten via en constructor eller en factory metode som tager instanser af C1..Cn som argument
* client laver instanser af subklasser af C1..Cn og instantierer S med disse

problemet er saa de nye metode i subklasserne

det kan loeses ved extension methods, men det kraever at:
- client laver en extension metode for hver metode der tilfoejes
- C1..Cn instanserne faktisk er visible for extension metoderne
- extension metoderne tester paa faktisk type via reflection og caster i forbindlese med forward af kald

det er ikke et attraktivt design

3) et alternativt approach var at generere S dynamisk udfra sub klasserne

det vil loese de 2 foerste problemer men det vil ikke loese det sidste problem

det er derfor heller ikke et attraktivt design

4) jeg tror ikke at der er en paen loesning
Avatar billede scorp-d Nybegynder
09. juni 2011 - 09:41 #4
Sad faktisk bare og ventede på at du kom med dit input.

Kan lige komme med "lidt" info, med hvordan det er opbygget i vores kørende test-miljø, som pt. ser ud til at fungere både funktionsmæssigt, og for slutbrugeren(udvikler):



De enkelte klasser(C) er reelt set felt-mapping fra tabeller, filer, webservices etc. 1:1 (men ikke 1:1 ift. backenden), som bliver valideret og "typecasted" til de extended data typer der matcher.


Den fælles klasse(S) er en data contract, som benytter én eller flere C-klasser(normalt 2-4 stk.) til at lave en reel 1:1 mapping ift. backenden, men hvor den kun indeholder de felter backenden kan bruge til noget.

Grunden til at alle felter ikke er implementeret, er dels for at give overskuelighed, og dels fordi  at det ikke er sikkert at alle typer datasources indeholder samtlige felter.


Under data contract(S) ligger der så en klasse(L) som står for den reelle import samt pre/post events på backenden.



Den samme c-klasse kan benyttes af én eller flere data contracts, og den samme data contract kan bruges i én eller flere L-klasser.


Reelt set matcher de klasser der er lavet, til en standard backend samt standard datasouces, men nu plejer standard og slutbruger(udvikler) ikke altid at hænge sammen:


Det kan være at de gerne vil benytte et ekstra felt i L-klassen,  som data contract'en(S) mangler, men som C-klasserne har.


Det kan også være at det felt ikke eksistere i C-klasserne, da de har tilføjet det til en standard datasource.


Eller at de gerne vil lave en ny data contract(S) på baggrund af en eksisterende, som fx benytter én C-klasse som matcher en tabel, og én som matcher en webservice.
Avatar billede arne_v Ekspert
25. juni 2011 - 23:36 #5
Hvis du kan leve med en statisk loesning, saa generer S udfra hvilke C der oenskes og byg klienter mod den.

hvis du vil have det mere dynamisk, saa give koeb paa type sikkerheden og brug name-value pairs aka Dictionary<string,object>.
Avatar billede scorp-d Nybegynder
26. juni 2011 - 20:51 #6
Okay... Du kan bare smide et svar...
Avatar billede arne_v Ekspert
27. juni 2011 - 00:59 #7
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester