Einzelnen Beitrag anzeigen

norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#1

Anfängerfragen zu Klassenaufbau

  Alt 4. Nov 2017, 10:07
Hallo zusammen,

ich bin dabei mich verstärkt in die Verwendung von Klassen einzuarbeiten und stoße immer wieder auf Unsicherheiten. Ich habe mal folgenden Klassenaufbau implementiert:
Delphi-Quellcode:
unit Unit5;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Generics.Collections, Vcl.StdCtrls;

type
  // Aufbau der Klassenstruktur
  // ...TTest
  // ....└─ TTestplan
  // ........└─ THardware
  // ............└─ THardwareList (TObjectList<THardwareBase>)
  // ................├─ THardwarePower (THardwareBase)
  // ................|...├─ TConfigPower (TConfigBase)
  // ................|...└─ TProcPower
  // ................└─ THardwareSpeed (THardwareBase)
  // ....................├─ TConfigSpeed (TConfigBase)
  // ....................└─ TProcSpeed

  TForm1 = class(TForm)
    btReadPower: TButton;
    Label1: TLabel;
    btCreateTest: TButton;
    btCreatePower: TButton;
    procedure btReadPowerClick(Sender: TObject);
    procedure btCreateTestClick(Sender: TObject);
    procedure btCreatePowerClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  TConfigBase = class
    ID : Integer;
    Name : String;
    Port : String;
    constructor Create;
    destructor Destroy; override;
  end;

  TConfigPower = class(TConfigBase)
    PowerRange : String;
  end;

  TConfigSpeed = class(TConfigBase)
    SpeedRange : String;
  end;

  TProcPower = class
    function GetPower:Real;
    constructor Create;
    destructor Destroy; override;
  end;

  TProcSpeed = class
    function GetSpeed: Real;
    constructor Create;
    destructor Destroy; override;
  end;

  THardwareBase = class
    Name : String;
    constructor Create;
    destructor Destroy; override;
  end;

  THardwarePower = class(THardwareBase)
    Config : TConfigPower;
    Proc : TProcPower;
    constructor Create;
    destructor Destroy; override;
  end;

  THardwareSpeed = class(THardwareBase)
    Config : TConfigSpeed;
    Proc : TProcSpeed;
    constructor Create;
    destructor Destroy; override;
  end;

  THardwareList = class(TObjectList<THardwareBase>)
  public
    function GetHardwarePower: THardwarePower;
    function GetHardwareSpeed: THardwareSpeed;
  end;

  THardware = class
    Name : String;
    HardwareList : THardwareList;
    constructor Create;
    destructor Destroy; override;
  end;

  TTestplan = class
    Name :String;
    Hardware : THardware;
    constructor Create;
    destructor Destroy; override;
  end;

  TTest = class
    Name :String;
    Testplan : TTestplan;
    constructor Create;
    destructor Destroy; override;
  end;

var
  Form1: TForm1;
  Test : TTest;

implementation

{$R *.dfm}

{ TConfigBase }

constructor TConfigBase.Create;
begin

end;

destructor TConfigBase.Destroy;
begin

  inherited;
end;

{ TProcPower }

constructor TProcPower.Create;
begin

end;

destructor TProcPower.Destroy;
begin

  inherited;
end;

function TProcPower.GetPower: Real;
begin

end;

{ TProcSpeed }

constructor TProcSpeed.Create;
begin

end;

destructor TProcSpeed.Destroy;
begin

  inherited;
end;

function TProcSpeed.GetSpeed: Real;
begin

end;

{ THardwareBase }

constructor THardwareBase.Create;
begin

end;

destructor THardwareBase.Destroy;
begin

  inherited;
end;

{ THardwarePower }

constructor THardwarePower.Create;
begin
  Config := TConfigPower.Create;
  Proc := TProcPower.Create;
end;

destructor THardwarePower.Destroy;
begin
  Config.Free;
  Proc.Free;

  inherited;
end;

{ THardwareSpeed }

constructor THardwareSpeed.Create;
begin
  Config := TConfigSpeed.Create;
  Proc := TProcSpeed.Create;
end;

destructor THardwareSpeed.Destroy;
begin
  Config.Free;
  Proc.Free;

  inherited;
end;

{ THardwareList }

function THardwareList.GetHardwarePower: THardwarePower;
var
  lObject: TObject;
begin
  Result := nil;
  for lObject in self do
    if lObject is THardwarePower then
    begin
      Result := lObject as THardwarePower;
      break;
    end;
end;

function THardwareList.GetHardwareSpeed: THardwareSpeed;
begin

end;

{ THardware }

constructor THardware.Create;
begin
  HardwareList := THardwareList.Create(true);
end;

destructor THardware.Destroy;
begin
  HardwareList.Free;

  inherited;
end;

{ TTestplan }

constructor TTestplan.Create;
begin

end;

destructor TTestplan.Destroy;
begin
  Hardware.Free;

  inherited;
end;

{ TTest }

constructor TTest.Create;
begin

end;

destructor TTest.Destroy;
begin
  Testplan.Free;

  inherited;
end;

procedure TForm1.btCreateTestClick(Sender: TObject);
begin
  if not assigned(Test) then
  begin
    Test := TTest.Create;
    Test.Testplan := TTestplan.Create;
    Test.Testplan.Hardware := THardware.Create;
  end;
end;

procedure TForm1.btReadPowerClick(Sender: TObject);
begin
  if assigned(Test) and
     assigned(Test.Testplan) and
     assigned(Test.Testplan.Hardware) and
     assigned(Test.Testplan.Hardware.HardwareList) and
     (Test.Testplan.Hardware.HardwareList.GetHardwarePower <> nil) then
       Label1.Caption := Test.Testplan.Hardware.HardwareList.GetHardwarePower.Name
  else
    Label1.Caption := 'Keine Leistungsmessgerät gefunden';
end;

procedure TForm1.btCreatePowerClick(Sender: TObject);
var
  HardwarePower : THardwarePower;
begin
  HardwarePower := THardwarePower.Create;
  HardwarePower.Name := 'Fluke 300';
  Test.Testplan.Hardware.HardwareList.Add(HardwarePower);
end;

end.
Dieser Aufbau ist stark vereinfacht, weshalb man nicht zuviel Zeit in Sinn oder Unsinn stecken sollte. In der Realklasse sind auch private/public-Bereiche und Properties verwendet. Das wichtige ist mir die Struktur der Klassen mit Unterklassen, und die THardwareList, die unterschiedliche Objekte aufnehmen kann. Jedes Objekt kann dabei nur einmal vorkommen. Es müssen aber nicht alle möglichen Objekte in der Liste vorhanden sein. Wie im Beispiel oben, wo nur HardwarePower in der Liste enthalten ist.

Meine Frage sind:
  • Wie kann man in der Abfrage btReadPower vermeiden, dass für jede Instanz erst abgefragt werden muss, ob sie erstellt wurde? In der Realklasse könnte es sein, dass z.B. keine Hardware definiert wurde.
  • Muss man THardwarePower ein eigenes Create erstellen oder reicht es aus, das von THardwareBase aufzurufen
  • Welche Unterschiede ergeben sich, ob ich THardwareList = class(TObjectList<THardwareBase>) oder THardwareList = class(TObjectList<TObject>) definiere?
  • Gibt es grundsätzliche Fehler im Aufbau?

Vielen Dank für eure Unterstützung
Gerd

Geändert von norwegen60 ( 4. Nov 2017 um 10:11 Uhr)
  Mit Zitat antworten Zitat