![]() |
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; |
AW: Setter mehrfach überschreiben.
Nö, so wird ein Schuh draus:
Delphi-Quellcode:
Sonst baust Du ja die Logik nach, die Dir durch OOP zur Verfügung gestellt wird.
Procedure TWerkzeug0.SetProperties();
begin ... end; Procedure TWerkzeug1.SetProperties(); begin inherited SetProperties(); ... end; ... |
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:
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)
Type
IWerkzeugPropertySetter = interface SetProperties(Item : TWerkzeug0); end; procedure TDrawPadProperties.SetProperties(Item: TWerkzeug0); var propertySetter : IWerkzeugPropertySetter; begin propertySetter := WerkzeugPropertySetterFactory.Create(Item); propertySetter.SetProperties(Item); end;
Delphi-Quellcode:
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.
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; |
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; |
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.
|
AW: Setter mehrfach überschreiben.
Ei, ich hann gemennt.. :)
|
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? |
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. |
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.
|
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:
und in Deinen abgeleiteten Klassen führst Du private Detaileigenschaften ein:
TBaseClass = class
public procedure Paint; virtual; end;
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 22:12 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