AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis
Thema durchsuchen
Ansicht
Themen-Optionen

Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

Ein Thema von MarioM. · begonnen am 25. Jul 2012 · letzter Beitrag vom 26. Jul 2012
Antwort Antwort
MarioM.

Registriert seit: 29. Mai 2006
52 Beiträge
 
#1

Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 25. Jul 2012, 14:39
Delphi-Version: 2010
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?
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#2

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 25. Jul 2012, 16:39
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.
Angehängte Dateien
Dateityp: pas Project1.dpr.pas (3,3 KB, 3x aufgerufen)
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 04:02
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.

Geändert von Namenloser (26. Jul 2012 um 17:29 Uhr) Grund: Properties bei Interface vergessen
  Mit Zitat antworten Zitat
MarioM.

Registriert seit: 29. Mai 2006
52 Beiträge
 
#4

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 07:49
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.
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#5

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 09:47
Delphi-Quellcode:
Var
   GDatenklasse: TDatenklasse;

Implementation

{ TAufgabeBasis }
Jetzt müsste nur noch die Projekt-Globale-Variable verschwinden...

Delphi-Quellcode:

Implementation

Var
   GDatenklasse: TDatenklasse;

{ TAufgabeBasis }
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 10:09
Wofür wird diese globale Variable überhaupt benötigt?

mE ist die total unsinnig
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#7

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 10:14
Wofür wird diese globale Variable überhaupt benötigt?

mE ist die total unsinnig
Für die gemeinsame Datenbasis. Schau dir mal den Konstruktur an.
  Mit Zitat antworten Zitat
MarioM.

Registriert seit: 29. Mai 2006
52 Beiträge
 
#8

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 10:50
Jetzt müsste nur noch die Projekt-Globale-Variable verschwinden...
Upsi - danke für den Hinweis
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Klassenstruktur / Basisklasse -> Kindklassen => gleiche Datenbasis

  Alt 26. Jul 2012, 12:04
Wofür wird diese globale Variable überhaupt benötigt?

mE ist die total unsinnig
Für die gemeinsame Datenbasis. Schau dir mal den Konstruktur an.
Jetzt wo du es sagst ... hmmm also ein heimliches Singleton durch die Hintertür ... ok, wenn es so läuft
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz