The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.
Probeer altijd composition te gebruiken ipv inheritance, als je later een ander type collectie wil gebruiken hoef je er gewoon voor te zorgen dat deze dezelfde interface als je collectie nu implementeert en dan kan je die gewoon vervangen in je code. Je bent niet meer gebonden aan 1 type collectie nu...
"Live as if you were to die tomorrow. Learn as if you were to live forever"
Ik heb nu in Delphi ongeveer het volgende:
1
2
3
4
5
6
7
8
| TBoom= Class(TObject); TLBomen = Class(TObjectList); //(+functies voor get/set van TBoom) TStraat = Class(TObject) private Bomen : TLBomen end; |
TLBomen is dus een wrapper om de TObjectList zodat deze alleen objecten van het type Boom kan bevatten.
Op zich toch een nette constructie, of maak ik nu een fout?
The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.
Eén van de OO ontwerp - guidelines is 'favor composition over inheritance'.Waarom geen inheritance? Ik heb nog niet veel gebruik gemaakt van composition
Natuurlijk, het moet nog bruikbaar zijn, en 'passen'. Dit wil nu niet zeggen dat je altijd in iedere situatie composition zou moeten gebruiken.
Soit.
Wat zou een THuizenList méér bieden qua functionaliteit dan een gewone TObjectList die je public maakt ?
Kan je in dit geval 'forceren' dat de Add method van een THuizenList enkel een object van het type THuis neemt ?
De AddHuis aanpak (de eerste aanpak) geeft als voordeel dat je op de een of andere manier eenvoudig een 'gecontroleerde' Add method hebt. Ik bedoel: stel dat je in een THuis een referentie bijhoudt naar de straat waarin dat huis staat, dan kan je dat makkelijk in de AddHuis method doen.
Dé enige juiste manier bestaat niet. Iedere aanpak heeft z'n voor- en nadelen. Aan jou om die aanpak te kiezen die voor jou, in deze bepaalde situatie, het beste werkt.
https://fgheysels.github.io/
Dat is dus voor mij een van de voornaamste redenen. Het model dat ik aan het maken ben gaat gebruikt worden om op basis van mijn classes te modelleren (ik ben een soort modelleer omgeving aan het maken).Kan je in dit geval 'forceren' dat de Add method van een THuizenList enkel een object van het type THuis neemt ?
Ik wil de modelleerder (die ook in Delphi gaat werken, maar dus met de door mij gedefinieerde classes) een duidelijke en overzichtelijke toolbox geven. Vandaar dat ik graag gebruik maak van de mogelijkheden die Delphi biedt in de IDE als de classes allemaal netjes gedefinieerd zijn. Op die manier kan hij niet eens compilen als er een keer een TBoom en een TLanterenpalenList wordt gestopt, zeg maar.
The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.
Verwijderd
Waarom?whoami schreef op woensdag 02 augustus 2006 @ 14:47:
Eén van de OO ontwerp - guidelines is 'favor composition over inheritance'.
Net even snel het simpele voorbeeldje uit deze link (Rectangle en Square) nagebouwd in Delphi: TSquareI inherit van TRectangle, TSquareC gebruikt composition. Ik weet wel welke ik prettiger en logischer vind, en dat is niet de laatste...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
| interface type TRectangle = class private FWidth: integer; FHeight: integer; public constructor Create(Width, Height: integer); procedure SetSize(Width, Height: integer); function GetArea: integer; end; TSquareI = class(TRectangle) public constructor Create(Size: integer); reintroduce; procedure SetSize(Size: integer); reintroduce; end; TSquareC = class private FRectangle: TRectangle; public constructor Create(Size: integer); destructor Destroy; override; procedure SetSize(Size: integer); function GetArea: integer; end; implementation { TRectangle } constructor TRectangle.Create(Width, Height: integer); begin SetSize(Width, Height); end; procedure TRectangle.SetSize(Width, Height: integer); begin FWidth := Width; FHeight := Height; end; function TRectangle.GetArea: integer; begin Result := FWidth * FHeight; end; { TSquareI } constructor TSquareI.Create(Size: integer); begin SetSize(Size); end; procedure TSquareI.SetSize(Size: integer); begin inherited SetSize(Size, Size); end; { TSquareC } constructor TSquareC.Create(Size: integer); begin FRectangle := TRectangle.Create(Size, Size); end; destructor TSquareC.Destroy; begin FRectangle.Free; end; procedure TSquareC.SetSize(Size: integer); begin FRectangle.SetSize(Size, Size); end; function TSquareC.GetArea: integer; begin Result := FRectangle.GetArea; end; |
Wanneer je THuizenList weet bij welke TStraat 'ie hoort (1 private member, en een constructor override), dan kan 'ie dat zelf ook prima (laten) bijhouden.De AddHuis aanpak (de eerste aanpak) geeft als voordeel dat je op de een of andere manier eenvoudig een 'gecontroleerde' Add method hebt. Ik bedoel: stel dat je in een THuis een referentie bijhoudt naar de straat waarin dat huis staat, dan kan je dat makkelijk in de AddHuis method doen.
Ik heb ook niet gezegd dat je het altijd moet gebruiken; gebruik inheritance wanneer inheritance het beste werkt, gebruik composition als dat het beste werkt.
Zolang je een 'Is a' relatie hebt, kan je inheritance gebruiken.
Een Square is een rectangle.
Ik bedoel dit:Wanneer je THuizenList weet bij welke TStraat 'ie hoort (1 private member, en een constructor override), dan kan 'ie dat zelf ook prima (laten) bijhouden.
(pseudo-code)
1
2
3
4
5
6
7
8
9
10
| class Straat
{
private Collection HuizenList;
public void AddHuis( Huis h )
{
h.Straat = this;
HuizenList.Add (h);
}
} |
[ Voor 33% gewijzigd door whoami op 03-08-2006 23:39 ]
https://fgheysels.github.io/
Verwijderd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| interface type THuizenList = class(TList) private FStraat: TStraat; public constructor Create(AStraat: TStraat); function Add(Huis: THuis): integer; override; end; implementation { THuizenList } constructor THuizenList.Create(AStraat: TStraat); begin inherited Create; FStraat := AStraat; end; function THuizenList.Add(Huis: THuis): integer; begin Huis.Straat := FStraat; inherited; end; |
Nu leg ik de 'intelligentie' bij de HuizenList om die straat te zetten, en een stukje intelligentie bij de Straat (die moet aan de HuizenList vertellen dat 'ie 'm aanmaakt). Beide hebben voor en nadelen, maar mijn voorkeur gaat uit naar de controle op de Add method te leggen bij de list/collection die 't betreft, en niet bij het object dat die list toevallig heeft aangemaakt.
Ik hou het dus bij de 2e manier: voor iedere class een eigen containerclass. Beetje meer werk, maar het wordt wel een hele mooie toolkit op die manier.
The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.