![]() |
Probleme im Klassendesign-Objektliste und Typ der Einträge
Hallo
Ich habe in meinem code viele Objekte und Objektlisten, die sich selbst in einen stream speichern und laden können und wie folgt aufgebaut sind
Delphi-Quellcode:
Savetostream der beiden entsprechend. Die Version dient mir zum flexiblen Erweitern der Datei um neue Eigenschaften.
//Liste
procedure TObjektListe.LoadFromStream(Stream: TStream); Var Version:integer; i,len:integer; Eintrag: TListeneintrag; begin clear; with TReader.create(Stream,FileStreamBuffer) do try //Version auslesen Version:=ReadInteger; len:=readinteger; … weitere Eigenschaften aus stream laden finally free; end; //einträge auslesen for i:=0 to len-1 do begin Eintrag:= TListeneintrag.Create; Eintrag.LoadFromStream(stream); add(Eintrag); end; end; //Eintrag: procedure TListeneintrag.LoadFromStream(Stream: TStream); var Version:integer; begin with TReader.create(Stream,FileStreamBuffer) do try //Version auslesen Version:=ReadInteger; Eigenschaft1 := ReadString; Eigenschaft2 := ReadString; … If Version>Version43 then EigenschaftXYZ := ReadString; finally free; end; end; Ich möchte gern diesen code, dessen Rumpfbereich in allen Objekten und ObjektListen vorkommt gern verallgemeinern, da der code sich ständig wiederholt und ich teilweise einen Haufen Warnungen wegen der Nichtbenutzung der Version erhalte (nicht jedes Objekt ändert sich ständig im Dateiaufbau). Ich hätte gern ein Basisobjekt, das wie folgt aussieht:
Delphi-Quellcode:
Das abgeleitete Objekt soll nur die Daten lesen und schreiben, der Reader/Writer soll im Basisobjekt bei load/savetostream erstellt werden, das abgeleitete Objekt soll davon nichts mitbekommen.
TBasisListenEintrag=class…
Private Procedure LoadfromStream… Procedure Savetostream… Public Procedure SaveData… //soll die abgeleitete Klasse Procedure Loaddata… //erst implementieren …. procedure TBasisListenEintrag.LoadFromStream(Stream: TStream); var DateiVersion:integer; begin with TReader.create(Stream,FileStreamBuffer) do try //Version auslesen Dateiversion:=ReadInteger; LoadData(Reader,Dateiversion) finally free; end; end; //abgeleitetes Objekt: procedure TAbgeleiteterListenEintrag.LoadData(Reader:Treader;const Dateiversion:integer); begin with reader do begin Eigenschaft1 := ReadString; Eigenschaft2 := ReadString; … If DateiVersion>Version43 then EigenschaftXYZ := ReadString; end; end; Für das Objekt ist das auch kein Problem, scheitern tue ich an der Objektliste
Delphi-Quellcode:
Bei Eintrag:= T????.Create; müsste ich wissen, welche abgeleitete Klasse die Objektliste verwaltet. Wenn ich Eintrag als TBasisobjekt angebe, rufe zwar loadfromstream auf, aber an das eigentliche auslesen der Daten per loaddata komm ich nicht ran.
procedure TBasisObjektList.LoadFromStream(Stream: TStream);
Var Version:integer; i,len:integer; Eintrag: T????; begin clear; with TReader.create(Stream,FileStreamBuffer) do try //Version auslesen Version:=ReadInteger; len:=readinteger; //weitere Eigenschaften aus stream laden Loaddata(…) finally free; end; //einträge auslesen for i:=0 to len-1 do begin Eintrag:= T????.Create; Eintrag.LoadFromStream(stream); add(Eintrag); end; end; Geht das überhaupt? Kann ich die Objektliste z.B. so flexibel gestalten das man z.B. beim create der objektliste den Typ der Einträge mit übergeben kann, oder gibt es eine andere Lösungsmöglichkeit? Danke im Voraus Frank |
Re: Probleme im Klassendesign-Objektliste und Typ der Einträ
Hallo Frank,
rein theoretisch müsstest du nur LoadData() in der Basisklasse als virtual deklarieren und in der abgeleiteten Klasse mit der override Direktive überschreiben. Machst du das schon so? Grüße vom marabu |
Re: Probleme im Klassendesign-Objektliste und Typ der Einträ
Hallo Marabu,
ich hatte (als einen von vielen Versuche ;) ) loaddata in der Basisklasse als virtuel abstract. wenn ich in der basisobjektliste dann
Delphi-Quellcode:
stehen habe, lande ich in abstrakten Fehler. Ich rufe zwar loadfromstream des Basisobjektes auf, aber das weiß mit loaddata dann auch nicht wohin, da dies erst im abgeleiteten Objekt implementiert wird. ich müßte Eintrag:= TAbgeleitetesobjekt.Create; stehen haben, aber welches AbgeleiteteObjekt die Liste verwaltet, weiß die Basisliste nicht.
//einträge auslesen
for i:=0 to len-1 do begin Eintrag:= TBasisobjekt.Create; Eintrag.LoadFromStream(stream); add(Eintrag); end; |
Re: Probleme im Klassendesign-Objektliste und Typ der Einträ
Hi,
der wahrscheinlich üblichste, schönste, was weiß ich Weg ist es wohl Templates zu benutzen oder Generics (weiß gerade nicht wie die in Delphi heißen). Ein vielleicht nicht so schöner aber allemal einfacher Weg ist es, wenn du mit einer Variablen als Metaklasse arbeitest. Dazu brauchst du nur so etwas wie
Delphi-Quellcode:
Ein Problem dass du hierbei bekommen könntest ist natürlich, dass du nicht immer den Standardkonstruktor zur Verfügung hast und du eventuell nicht weißt, was für Parameter du bekommst.
type
TMetaClass = class of TObject; ... var x : TMetaClass; begin x := TStringList; // oder halt eine beliebige Klasse, die Nachfahre von TObject ist result := x.Create; end; Hoffe es hilft dir trotzdem weiter Gruß Der Unwissende |
Re: Probleme im Klassendesign-Objektliste und Typ der Einträ
:-D, Danke. Das sieht erstmal gut aus, damit muß ich mich näher beschäftigen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz