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
God-Object mutieren könnte):
Delphi-Quellcode:
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;
Und dann so:
Delphi-Quellcode:
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
Interfaces und Objekte auf diese Art zu mischen kann übrigens auch wegen der Referenzzählung bei Interfaces nach hinten losgehen, wenn man nicht aufpasst.