![]() |
Delphi-Version: 2010
Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Hallo zusammen,
ich stehe vor folgendem Problem. Ich möchte gerne aus Daten, die ich in Objekten sammle, eine XML-Struktur aufbauen, mit der Aufgaben übermittelt werden; das aber nur als Hintergrund. Das Ganze soll so aussehen, dass es verschiedene Aufgaben gibt, für die bestimmte Tags im XML gefüllt werden sollen. Um den Anwender der Klassen möglichst gut zu führen, habe ich das Ganze so aufgebaut, dass ich eine Basisklasse habe, die alle möglichen Felder enthält, die in den Aufgaben vorkommen können. Zusätzlich habe ich für jede mögliche Aufgabe eine Klasse von dieser Basisklasse abgeleitet, und nur die Eigenschaften public gesetzt, die für die Aufgabe relevant sind. So sieht der Anwender genau, wenn er eine Instanz einer Aufgaben-Klasse erzeugt, welche Informationen benötigt werden. Jetzt nehmen wir mal an, die Information NAME ist sowohl für Aufgabe1 als auch Aufgabe2 relevant. Ich möchte aber, dass Aufgabe1.NAME überschrieben wird, wenn Aufgabe2.NAME gesetzt wird - alle Aufgabensollen also auf die gleichen Daten zugreifen, und nicht jede Aktion einen eigenen Datenbereich haben. In der Basisklasse sind alle Felder private, die entsprechenden Properties dazu protected. Was in der Ableitung zugänglich sein soll, habe ich dort public gemacht. wie lässt sich das realisieren? |
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Liste der Anhänge anzeigen (Anzahl: 1)
Den Teil mit dem XML habe ich nicht verstanden. Aber es klingt danach als müsste man dafür die Klasse TDaten in meinem Vorschlag ändern. Für alles andere: So vielleicht? -- Vorschlag im Anhang.
|
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Verstehe ich das richtig, dass alle Klassen auf die gleiche Datenstruktur zugreifen und du willst, dass alle Änderungen synchron sind?
In dem Fall solltest du deine Klassenstruktur anders aufbauen – das, was aktuell deine Basisklasse ist, sollte eine unabhängige Dokument-Klasse sein. [edit]Oder du verwendest Interfaces, siehe unten.[/edit] Deine Aufgaben-Klassen können sich dann mit einer Instanz der Dokument-Klasse verbinden und auf deren Datenbestand zugreifen. Beispiel:
Delphi-Quellcode:
TDocument = class
public function GetProperty(Identifier: string): Variant; procedure SetProperty(Identifier: string; Value: Variant); end; TTaskBase = class protected FDocument: TDocument; public constructor Create(Document: TDocument); end; TTaskAlpha = class(TTaskBase) protected function GetPropertyA: Integer; procedure SetPropertyA(Value: Integer); function GetPropertyB: String; procedure SetPropertyB(Value: String); public property PropertyA: Integer read GetPropertyA write SetPropertyA; property PropertyB: String read GetPropertyB write SetPropertyB; end; TTaskBeta = class(TTaskBase) protected function GetPropertyA: Integer; procedure SetPropertyA(Value: Integer); function GetPropertyC: Boolean; procedure SetPropertyC(Value: Boolean); public property PropertyA: Integer read GetPropertyA write SetPropertyA; property PropertyC: Boolean read GetPropertyC write SetPropertyC; end; implementation constructor TTaskBase.Create(Document: TDocument); begin inherited Create; FDocument := Document; end; function TTaskAlpha.GetPropertyA: Integer; begin Result := FDocument.GetProperty('A'); end; procedure TTaskAlpha.SetPropertyA(Value: Integer); begin FDocument.SetProperty('A', Value); end; function TTaskAlpha.GetPropertyB: String; begin Result := FDocument.GetProperty('B'); end; procedure TTaskAlpha.SetPropertyB(Value: String); begin FDocument.SetProperty('B', Value); end; function TTaskBeta.GetPropertyA: Integer; begin Result := FDocument.GetProperty('A'); end; procedure TTaskBeta.SetPropertyA(Value: Integer); begin FDocument.SetProperty('A', Value); end; function TTaskBeta.GetPropertyC: Boolean; begin Result := FDocument.GetProperty('C'); end; procedure TTaskBeta.SetPropertyC(Value: Boolean); begin FDocument.SetProperty('C', Value); end;
Delphi-Quellcode:
var
Document: TDocument; TaskAlpha: TTaskAlpha; TaskBeta: TTaskBeta; begin Document := TDocument.Create(...); // * Document irgendwie initialisiert * TaskAlpha := TTaskAlpha.Create(Document); TaskBeta := TTaskBeta.Create(Document); // Property A ändert ihren Wert synchron: TaskAlpha.PropertyA := 42; writeln(TaskAlpha.PropertyA); // gibt 42 aus writeln(TaskBeta.PropertyA); // gibt 42 aus TaskBeta.PropertyA := 314; writeln(TaskAlpha.PropertyA); // gibt 314 aus writeln(TaskBeta.PropertyA); // gibt 314 aus // Diese Properties werden im Beispiel nur von jeweils einer Aufgabenklasse benutzt: TaskAlpha.PropertyB := 'Foo'; TaskBeta.PropertyC := True; Edit: Eine andere Variante wäre, mit Interfaces zu arbeiten – das entspräche eher deinem bisherigen Ansatz. Aber das geht natürlich nur, wenn deine Aufgabenklassen kein neues Verhalten (z.B. neue Methoden) einführen, sondern ausschließlich Untermengen der Mutterklasse bereitstellen (wobei die Klasse tendenziell zum ![]()
Delphi-Quellcode:
Und dann so:
ITaskAlpha = interface
function GetPropertyA: Integer; procedure SetPropertyA(Value: Integer); function GetPropertyB: String; procedure SetPropertyB(Value: String); property PropertyA: integer read GetPropertyA write SetPropertyA; property PropertyB: string read GetPropertyB write SetPropertyB; end; ITaskBeta = interface function GetPropertyA: Integer; procedure SetPropertyA(Value: Integer); function GetPropertyC: Boolean; procedure SetPropertyC(Value: Boolean); property PropertyA: integer read GetPropertyA write SetPropertyA; property PropertyC: boolean read GetPropertyC write SetPropertyC; end; TDocument = class(TInterfacedObject, ITaskAlpha, ITaskBeta) function GetPropertyA: Integer; procedure SetPropertyA(Value: Integer); function GetPropertyB: String; procedure SetPropertyB(Value: String); function GetPropertyC: Boolean; procedure SetPropertyC(Value: Boolean); end;
Delphi-Quellcode:
Interfaces und Objekte auf diese Art zu mischen kann übrigens auch wegen der Referenzzählung bei Interfaces nach hinten losgehen, wenn man nicht aufpasst.
var
Document: TDocument; TaskAlpha: ITaskAlpha; TaskBeta: ITaskBeta; begin Document := TDocument.Create(...); // * Document irgendwie initialisiert * TaskAlpha := Document as ITaskAlpha; TaskBeta := Document as ITaskBeta; // Rest wie oben |
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Hallo, und danke für Eure ausführlichen Beispiele.
Ich habe das Ganze nun so implementiert; und es funktioniert :)
Delphi-Quellcode:
Unit Unit1;
Interface Uses SysUtils; Type TTestArray = Array Of String; TDatenklasse = Class private FWert1: String; FWert2: String; FWert3: Integer; FWert4: TTestArray; End; TAufgabeBasis = Class private FDatenklasse: TDatenklasse; Function GetWert1: String; Function GetWert2: String; Function GetWert3: Integer; Procedure SetWert1(Const Value: String); Procedure SetWert2(Const Value: String); Procedure SetWert3(Const Value: Integer); Function GertWert4: TTestArray; protected Property Wert1: String read GetWert1 write SetWert1; Property Wert2: String read GetWert2 write SetWert2; Property Wert3: Integer read GetWert3 write SetWert3; Property Wert4: TTestArray read GertWert4; Procedure AddToWert4(Value: String); virtual; public Constructor Create; End; TAufgabe1 = Class(TAufgabeBasis) public Property Wert1; Property Wert2; Procedure AddToWert4(Value: String); override; End; TAufgabe2 = Class(TAufgabeBasis) public Property Wert2; Property Wert3; Procedure AddToWert4(Value: String); override; End; Var GDatenklasse: TDatenklasse; Implementation { TAufgabeBasis } // ******************************************************************** Procedure TAufgabeBasis.AddToWert4(Value: String); Begin SetLength(FDatenklasse.FWert4, Length(FDatenklasse.FWert4) + 1); FDatenklasse.FWert4[Length(FDatenklasse.FWert4) - 1] := Value; End; // ******************************************************************** Constructor TAufgabeBasis.Create; Begin FDatenklasse := GDatenklasse; End; // ******************************************************************** Function TAufgabeBasis.GertWert4: TTestArray; Begin Result := FDatenklasse.FWert4; End; // ******************************************************************** Function TAufgabeBasis.GetWert1: String; Begin Result := FDatenklasse.FWert1; End; // ******************************************************************** Function TAufgabeBasis.GetWert2: String; Begin Result := FDatenklasse.FWert2; End; // ******************************************************************** Function TAufgabeBasis.GetWert3: Integer; Begin Result := FDatenklasse.FWert3; End; // ******************************************************************** Procedure TAufgabeBasis.SetWert1(Const Value: String); Begin FDatenklasse.FWert1 := Value; End; // ******************************************************************** Procedure TAufgabeBasis.SetWert2(Const Value: String); Begin FDatenklasse.FWert2 := Value; End; // ******************************************************************** Procedure TAufgabeBasis.SetWert3(Const Value: Integer); Begin FDatenklasse.FWert3 := Value; End; // ******************************************************************** { TAufgabe2 } Procedure TAufgabe2.AddToWert4(Value: String); Begin Inherited; End; // ******************************************************************** { TAufgabe1 } Procedure TAufgabe1.AddToWert4(Value: String); Begin Inherited; End; // ******************************************************************** Initialization GDatenklasse := TDatenklasse.Create; Finalization FreeAndNil(GDatenklasse); End.
Delphi-Quellcode:
Unit Unit2;
Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Unit1; Type TForm2 = Class(TForm) Procedure FormCreate(Sender: TObject); private FAufgabe1: TAufgabe1; FAufgabe2: TAufgabe2; End; Var Form2: TForm2; Implementation {$R *.dfm} Procedure TForm2.FormCreate(Sender: TObject); Begin FAufgabe1 := TAufgabe1.Create; FAufgabe2 := TAufgabe2.Create; FAufgabe1.Wert1 := 'Wert1 aus Aufgabe 1'; FAufgabe1.Wert2 := 'Wert2 aus Aufgabe 1'; FAufgabe1.AddToWert4('Wert 4 aus Aufgabe 1'); FAufgabe2.Wert2 := 'Wert2 aus Aufgabe 2'; FAufgabe2.Wert3 := 3; FAufgabe2.AddToWert4('Wert 4 aus Aufgabe 2'); End; // ******************************************************************** End. |
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Zitat:
Delphi-Quellcode:
Implementation Var GDatenklasse: TDatenklasse; { TAufgabeBasis } |
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Wofür wird diese globale Variable überhaupt benötigt? :gruebel:
mE ist die total unsinnig |
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Zitat:
|
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Zitat:
|
AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:06 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