Delphi-PRAXiS
Seite 3 von 6     123 45     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Setter mehrfach überschreiben. (https://www.delphipraxis.net/185422-setter-mehrfach-ueberschreiben.html)

Bjoerk 10. Jun 2015 07:47

AW: Setter mehrfach überschreiben.
 
Ich hab diese fürchterliche Basisklasse geschreddert (nicht nur gelöscht). Die bringt überhaupt nichts null nothing gar nichts. Ich habe 3 Kategorien von geometrischen Objekten, die ich eh immer abfragen muß?

Beispiel:
Delphi-Quellcode:
procedure TDrawPadProperties.SetProperties(Item: TWerkzeug0);
var
  Item1: TWerkzeug1;
  Item2: TWerkzeug2;
  Item3: TWerkzeug3;
begin
  SetProperties0(Item);
  if Item is TWerkzeug1 then
  begin
    Item1 := TWerkzeug1(Item);
    SetProperties1(Item1);
  end
  else
    if Item is TWerkzeug2 then
    begin
      Item2 := TWerkzeug2(Item);
      SetProperties2(Item2);
    end
    else
    begin
      Item3 := TWerkzeug3(Item);
      SetProperties3(Item3);
    end;
end;

Mikkey 10. Jun 2015 07:56

AW: Setter mehrfach überschreiben.
 
Nö, so wird ein Schuh draus:

Delphi-Quellcode:
Procedure TWerkzeug0.SetProperties();
begin
    ...
end;

Procedure TWerkzeug1.SetProperties();
begin
    inherited SetProperties();
    ...
end;
...
Sonst baust Du ja die Logik nach, die Dir durch OOP zur Verfügung gestellt wird.

Dejan Vu 10. Jun 2015 08:24

AW: Setter mehrfach überschreiben.
 
Wieso schreibst Du dir keinen WerkzeugPropertySetter und eine Factory, die Dir zu dem Werkzeug ('Item') die passende Klasse liefert, welche dann die Daten setzt. Wenn bei deinem Ansatz nämlich noch ein TWerkzeug4 hinzukommt, musst Du deinen Code anpassen, und das wäre dann so gar nicht OCP.
Delphi-Quellcode:
Type
  IWerkzeugPropertySetter = interface
    SetProperties(Item : TWerkzeug0);
  end;

procedure TDrawPadProperties.SetProperties(Item: TWerkzeug0);
var
  propertySetter : IWerkzeugPropertySetter;

begin
  propertySetter := WerkzeugPropertySetterFactory.Create(Item);
  propertySetter.SetProperties(Item);
end;
Leider musst Du in den einzelnen Setterklassen dann dein 'Item' immernoch konkret auf TWerkzeugX casten, aber da Du keine Generics benutzt, bleibt dir hier dann wohl nichts anderes übrig. Mit Generics würde das so aussehen (so ungefähr jedenfalls)

Delphi-Quellcode:
Type
  IWerkzeugPropertySetter<T : TWerkzeug0> = interface
    SetProperties(Item : T);
  end;

  WerkzeugPropertySetterFactory = class
    Function Create<T : TWerkzeug0> (Item : T) : IWerkzeugPropertySetter<T>;
  End;

procedure TDrawPadProperties.SetProperties<T:TWerkzeug0>(Item: T);
var
  propertySetter : IWerkzeugPropertySetter<T>;

begin
  propertySetter := WerkzeugPropertySetterFactory.Create<T>(Item);
  propertySetter.SetProperties(Item);
end;
Und das wäre dann typsicher. Wenn nun ein 4. Werkzeug hinzukommst, schreibst Du eine neue Klasse dafür und registrierest diese in der Factory.

Bjoerk 10. Jun 2015 13:06

AW: Setter mehrfach überschreiben.
 
Weil der Typ TWerkzeug0 so was Ähnliches wie TCustomControl ist. Wirklich viel macht TWerkzeug0 noch nicht. Ich hab jetzt mal das vorbereitet. Ist an manchen Stellen eine Arbeitserleichterung. Wobei mich immer wundert daß man in Delphi "Bauer := TDame.Create" machen kann.
Delphi-Quellcode:
  TWerkzeugFactory = class
  private
    FTyp: TGraphicTyp;
    FWerkzeug: TWerkzeug0;
    procedure SetTyp(const Value: TGraphicTyp);
    procedure DoCreate;
    procedure DoDestroy;
    function GetWerkzeug1: TWerkzeug1;
    function GetWerkzeug2: TWerkzeug2;
    function GetWerkzeug3: TWerkzeug3;
    function GetIsWerkzeug1: boolean;
    function GetIsWerkzeug2: boolean;
    function GetIsWerkzeug3: boolean;
  public
    property Typ: TGraphicTyp read FTyp write SetTyp;
    property Werkzeug: TWerkzeug0 read FWerkzeug;
    property Werkzeug1: TWerkzeug1 read GetWerkzeug1;
    property Werkzeug2: TWerkzeug2 read GetWerkzeug2;
    property Werkzeug3: TWerkzeug3 read GetWerkzeug3;
    property IsWerkzeug1: boolean read GetIsWerkzeug1;
    property IsWerkzeug2: boolean read GetIsWerkzeug2;
    property IsWerkzeug3: boolean read GetIsWerkzeug3;
    destructor Destroy; override;
  end;

{ TWerkzeugFactory }

destructor TWerkzeugFactory.Destroy;
begin
  DoDestroy;
  inherited;
end;

procedure TWerkzeugFactory.DoCreate;
begin
  if Util_IsWerkzeug1(FTyp) then
    FWerkzeug := TWerkzeug1.Create
  else
    if Util_IsWerkzeug2(FTyp) then
      FWerkzeug := TWerkzeug2.Create
    else
      if Util_IsWerkzeug3(FTyp) then
        FWerkzeug := TWerkzeug3.Create
      else
        FWerkzeug := TWerkzeug0.Create;
end;

procedure TWerkzeugFactory.DoDestroy;
begin
  if Assigned(FWerkzeug) then
  begin
    FWerkzeug.Free;
    FWerkzeug := nil;
  end;
end;

procedure TWerkzeugFactory.SetTyp(const Value: TGraphicTyp);
begin
  DoDestroy;
  FTyp := Value;
  DoCreate;
end;

function TWerkzeugFactory.GetIsWerkzeug1: boolean;
begin
  Result := FWerkzeug is TWerkzeug1;
end;

function TWerkzeugFactory.GetIsWerkzeug2: boolean;
begin
  Result := FWerkzeug is TWerkzeug2;
end;

function TWerkzeugFactory.GetIsWerkzeug3: boolean;
begin
  Result := FWerkzeug is TWerkzeug3;
end;

function TWerkzeugFactory.GetWerkzeug1: TWerkzeug1;
begin
  if IsWerkzeug1 then
    Result := TWerkzeug1(FWerkzeug)
  else
    Result := nil;
end;

function TWerkzeugFactory.GetWerkzeug2: TWerkzeug2;
begin
  if IsWerkzeug2 then
    Result := TWerkzeug2(FWerkzeug)
  else
    Result := nil;
end;

function TWerkzeugFactory.GetWerkzeug3: TWerkzeug3;
begin
  if IsWerkzeug3 then
    Result := TWerkzeug3(FWerkzeug)
  else
    Result := nil;
end;

DeddyH 10. Jun 2015 13:13

AW: Setter mehrfach überschreiben.
 
Den Sinn dieser Factory verstehe ich ehrlich gesagt nicht. Kommt noch eine Ableitung hinzu, muss auch die Factory geändert werden, damit sie die entsprechende Klasseninstanz liefern kann, das bringt irgendwie nix.

Bjoerk 10. Jun 2015 13:20

AW: Setter mehrfach überschreiben.
 
Ei, ich hann gemennt.. :)

stahli 10. Jun 2015 13:21

AW: Setter mehrfach überschreiben.
 
Schreib doch mal, was Du da vor hast.
Willst Du nur eine Werkzeuginstanz?

Sollen das sichtbare Controls werden?

Was soll das Projekt machen und was die Fabrik?

Bjoerk 10. Jun 2015 14:29

AW: Setter mehrfach überschreiben.
 
Ok. Also: Ich habe 3 Klassen ala TShape (TWerkzeug1,2,3). Jede TWerkzeug Class kann so 15-25 Figuren zeichnen. Alles was in den Shapes gleich ist, befindet sich in der Basisklasse TWerkzeug0. Der User wählt mit dem Speedbutton eines von ca. 70 zu zeichnenden Objecte aus. Je nachdem in welcher Klasse das Objekt gezeichnet wird, muß also Werkzeug1,2,3.Draw ausgeführt werden. Draw befindet sich abstract in TWerkzeug0 und wird von Werkzeug1,2,3 überschrieben. Ist somit kein Problem. Das ist aber bei den Variablen nicht so. Deshalb hatte ich die Idee mit der aufgeblähten Klasse von #9. Davon wäre TWerkzeug0 abgeleitet gewesen. Alle Properties (Getter/Setter) würden überschrieben. Zurzeit muß ich explizit auf 1 oder 2 oder 3 prüfen. Zum Beispiel: TWerkzeug2 hat eine Property Polygon, Werkzeug1 und Werkzeug3 nicht. Ich muß also prüfen,

wenn Polygon -> dann TWerkzeug2 -> dann FWerkzeug2.Polygon.Add(X, Y).

Dieses Prüfen ob 1 2 oder 3 ist aber nicht so prickelnd und sehr viel Tipparbeit (gewesen). Und was ist wenn es mal 4 oder 5 Werkzeugkategorien werden sollten (wurde ja schon angesprochen).

Ich hatte im Bezug auf dieses Programm schon mehrere Threads hier und da wurde mir immer (oder öfter) eine Faktory empfohlen. Anscheinend hab ich das noch nicht ausreichend kapiert bzw. den Sinn einer Faktory nicht ganz verstanden.

Ich suche eigentlich nur ein elegantes Handling für diese 3 Klassen.

DeddyH 10. Jun 2015 14:54

AW: Setter mehrfach überschreiben.
 
Ohne die Klassen zu kennen: wäre es nicht möglich, eine Basis-Methode zu deklarieren (kann auch abstrakt sein) oder ersatzweise eine Property, die die abgeleiteten Klassen dann eben unterschiedlich behandeln? Statt also von außen Dings.Polygon.Add aufzurufen, wird eben der Weg über Basisklasse.AddPoint(X,Y) gegangen. AddPoint wird dabei unterschiedlich behandelt, aber eben nur intern, den Aufrufer schert das nicht.

stahli 10. Jun 2015 15:06

AW: Setter mehrfach überschreiben.
 
Genau.

Was die Controls zeichnen geht von außen niemanden etwas an.
Ob sie intern ein Polygon verwalten oder mehrere Farben oder Textumbrüche ist normalerweise Privatsache der spezialisierten Klasse.

Nach außen musst Du ja nur das öffentlich machen, was die Umgebung Deiner Werkzeuge interessiert.

Du kannst Deine Basisklasse ja rel. klein halten:

Delphi-Quellcode:
TBaseClass = class
public
  procedure Paint; virtual;
end;
und in Deinen abgeleiteten Klassen führst Du private Detaileigenschaften ein:

Delphi-Quellcode:
TClassA = class(TBaseClass)
private
  Polygon...
public
  procedure Paint; override;
end;

TClassB = class(TBaseClass)
private
  Text...
public
  procedure Paint; override;
end;

Die Daten musst Du natürlich ggf. von außen klassenspezifisch zuweisen, aber die Basisklasse muss ja nicht alle Varianten kennen sondern nur die einheitlichen Eigenschaften.


Eine Factory wird Dir hier nichts bringen. Ich denke, Du musst die Klasseneigenschaften nur besser nach tatsächlichen Aufgaben trennen.

Müssen Deine Klassen noch etwas anderes machen, als sich zu zeichnen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:22 Uhr.
Seite 3 von 6     123 45     Letzte »    

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