Tag auch
Ich möchte in einer Klasse verschiedene Array's verwalten, welche gemeinsam verwendete Methoden bereitstellt um die Daten zu manipulieren. Pro Objekt ist jedoch nur eines dieser Array's relevant, welches lege ich bereits beim erzeugen des Objektes fest. Das zu verwendene Array wird also nicht mehr gewechselt, sobald das Objekt erzeugt wurde.
Nun meine Frage. Wie realisiere ich am günstigsten diese Klasse, vorallem im Hinblick darauf, das ich später mit sehr vielen dieser Objekte arbeiten werde (Geschwindigkeit).
Ich habe mir dazu zwei Möglichkeiten ausgedacht.
1. Klasse mit virtuelle Methoden
Eine Klasse die Methoden zum Bearbeiten der Array's virtuell implementiert und diese dann in Nachfahrenklassen mit dem jeweiligen korrekten Datentyp überschrieben werden. Wobei nur die Nachfahrenklasse das eigentliche Array enthält.
Erzeugt wird dann nurnoch die entsprechende Nachfahrenklasse. Verwendet wird jedoch nurnoch die Elternklasse mit den virtuellen Methoden (damit spare ich mir dann die abfrage, welchen datentyp die Klasse denn nun tatsächlich enthält)
Bsp:
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:
| type TDatentyp = (dtInt8, dtFloat4); TWert = Variant;
TInt8Arr = array of ShortInt;
TFloat4Arr = array of Double;
TDaten = class(TObject) protected fDatentyp: TDatentyp; function GetWert(Index: Integer): TWert; virtual; abstract; procedure SetWert(Index: Integer; const Value: TWert); virtual; abstract; public property Wert[Index: Integer]: TWert read GetWert write SetWert; default; procedure WertHinzufuegen(Wert: Variant); virtual; abstract; constructor Create(Datentyp: TDatentyp); end;
TDatenInt8 = class(TDaten) private fArr: TInt8Arr; protected function GetWert(Index: Integer): TWert; override; procedure SetWert(Index: Integer; const Value: TWert); override; public procedure WertHinzufuegen(Wert: Variant); override; end;
TDatenFloat4 = class(TDaten) private fArr: TFloat4Arr; protected function GetWert(Index: Integer): TWert; override; procedure SetWert(Index: Integer; const Value: TWert); override; public procedure WertHinzufuegen(Wert: Variant); override; end;
implementation
constructor TDaten.Create(Datentyp: TDatentyp); begin fDatentyp:= Datentyp; end;
function TDatenInt8.GetWert(Index: Integer): TWert; begin Result:= fArr[Index]; end;
procedure TDatenInt8.SetWert(Index: Integer; const Value: TWert); begin fArr[Index]:= Value; end;
procedure TDatenInt8.WertHinzufuegen(Wert: Variant); begin SetLength(fArr, Length(fArr) + 1); fArr[Length(fArr) - 1]:= Wert; end; |
2. Array über case of auswählen
Die zweite Möglichkeit würde alle Array's in einer Klasse vereinen. Die je nach Datentyp über eine case of abfrage das entsprechende Array benutzt (und auch füllt, denn solange die anderen Array leer sind, dürften sie kein Speicherplatz verbrauchen).
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:
| TDatentyp = (dtInt8, dtFloat4); TWert = Variant;
TInt8Arr = array of ShortInt;
TFloat4Arr = array of Double;
TDaten = class(TObject) private fDatentyp: TDatentyp; fInt8Arr: TInt8Arr; fFloat4Arr: TFloat4Arr; function GetWert(Index: Integer): TWert; procedure SetWert(Index: Integer; const Value: TWert); public property Wert[Index: Integer]: TWert read GetWert write SetWert; default; procedure WertHinzufuegen(Wert: Variant); constructor Create(Datentyp: TDatentyp); end;
implementation
constructor TDaten.Create(Datentyp: TDatentyp); begin fDatentyp:= Datentyp; end;
function TDaten.GetWert(Index: Integer): TWert; begin case fDatentyp of dtInt8: Result:= fInt8Arr[Index]; dtFloat4: Result:= fFloat4Arr[Index]; end; end;
procedure TDaten.SetWert(Index: Integer; const Value: TWert); begin case fDatentyp of dtInt8: fInt8Arr[Index]:= Value; dtFloat4: fFloat4Arr[Index]:= Value; end; end;
procedure TDaten.WertHinzufuegen(Wert: Variant); begin case fDatentyp of dtInt8: begin SetLength(fInt8Arr, Length(fInt8Arr) + 1); fInt8Arr[Length(fInt8Arr) - 1]:= Wert; end; dtFloat4: begin SetLength(fFloat4Arr, Length(fFloat4Arr) + 1); fFloat4Arr[Length(fFloat4Arr) - 1]:= Wert; end; end; end; |
Da ich mich mit den interna von Vererbung etc. nicht wirklich auskenne, kann ich nicht beurteilen welche methode besser geeignet ist.
Ich habe auch irgendwo mal geselsen das eine case of abfrage relativ langsam ist.
Zu bedenken wäre auch, das es nicht bei diesen beiden beispiel Datentypen bleibt.
Deshalb meine Frage, welche methode ist am besten, bzw. gibt es alternativen?
mfg
cbs