AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Hilfklasse

Ein Thema von freimatz · begonnen am 25. Mai 2022 · letzter Beitrag vom 30. Mai 2022
Antwort Antwort
freimatz

Registriert seit: 20. Mai 2010
1.378 Beiträge
 
Delphi 11 Alexandria
 
#1

Hilfklasse

  Alt 25. Mai 2022, 07:32
Hoi, Sorry Betreff ist mir kein besserer eingefallen.
Es geht um eine Monsterklasse zu vereinfachen. Zum Beispiel (real ist anders)
Delphi-Quellcode:
IMonster = interface
property ElementTyp: TTyp; //Kreis, Quadrat, etc.
property ElementFarbe: TColor;
property ElementGroesse: Double;
...
property ReferenzTyp: TTyp;
property ReferenzFarbe: TColor;
property ReferenzGroesse: Double;
...
Die implementiere Klasse hat da Getter die auf interne Daten zugreifen. Nun hätte ich das gerne so:
Delphi-Quellcode:
IElement=interface
property Typ: TTyp; //Kreis, Quadrat, etc.
property Farbe: TColor;
property Groesse: Double;
...
IMonster = interface
property Element: IElement;
property Referenz: IElement;
Damit könnte ich mir etliche Properties sparen.
Statt Monster.ReferenzFarbe schreibt man dann halt Monster.Referenz.Farbe.
Aber wie implementiert man das dann? Klar: TElement = class(TInterfacedObject, IElement). Aber dann muss diese Klasse ja noch TMonster kennen. Oder es bekommt die Daten bei der Erzeugung mit. Dann muss die Klasse aber jedesmal neu erzeugt werden oder es braucht eine Benachrichtigung wenn sich die Daten ändern.
Kann ich alles machen aber scheint mir recht aufwendig. (Nein - Datenhaltung in TElement kommt nicht in Frage)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Hilfklasse

  Alt 25. Mai 2022, 08:46
Delphi-Quellcode:
constructor TMonster.Create;
begin
...
  FElement := TElement.Create(Self); //Übergabeparameter nach Lust und Laune benennen: Parent, Owner, Lieblingsonkel, Datengrab oder Mutti
  FReferenz := TElement.Create(Self);
...
end;
  Mit Zitat antworten Zitat
Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Hilfklasse

  Alt 25. Mai 2022, 08:46
Ich tue mich schwer das Beispiel zu verstehen. Element sind doch einfach nur Eigenschaften (Daten), keine Objekt, das etwas tut. Ich verstehe auch nicht, weshalb es TMonster/IMonster überhaupt kennen muss. Machen tut doch das Monster. Es guckt auf sein Feld Referenz oder Element und handelt entsprechend.

Geht es dir darum, in Monster direkt darauf zu reagieren, wenn man im Code z.B. sagt meinMonster.Referenz.Farbe := blau ? Dann würde man der Referenz im Konstruktor wohl einen Callback mitgeben den es aufrufen soll, wenn auf ihm was geändert wird. Oder es hat eine Event-Variable OnChange an die sich das Monster binden kann, um darauf zu reagieren dass in Referenz sich etwas geändert hat.

Ein "Real World Example" ist wohl z.B. meinLabel.Font.Size := xx . Da ist das auch so gelöst.

Klingt kompliziert? Ist es auch. Ich finde das Overkill. Und das hängt mit diesem Property-Gefummel zusammen, gegen das ich nicht müde werde zu wettern, aber damit stehe ich hier im Delphi-Forum eher alleine da.

Wie würde ich es machen?
  • Element ist ein Record mit Feldern "Größe", "Farbe" usw.
  • Element bekommt noch eine Operator-Überladung sodass ich z.B. sagen kann if elementNeu = elementAlt then ...
  • Ich gebe IMonster nur ein getElement(): TElement und setElement(const element: TElement)
  • In setElement(..) wird geprüft ob sich element überhaupt verändert hat, und wenn ja, dann tu etwas (z.B. zeichne dich neu)

Ja, statt meinMonster.Referenz.Farbe := blau tippe ich jetzt
Delphi-Quellcode:
referenz := meinMonster.getReferenz();
referenz.farbe := blau;
meinMonster.setReferenz(referenz);
Hebt sich aber auch schon wieder auf, wenn ich z.B. nicht nur Farbe, sondern auch Größe anpassen will. Ja, es sind ein paar Buchstaben mehr zu tippen wenn man was ändert. Aber an den anderen Stellen wird es so viel simpler: Die Daten sind an einem Platz, und sind wirklich nur Daten, und ich brauche keine Callbacks für Änderungen "eins weiter unten".
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.378 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Hilfklasse

  Alt 25. Mai 2022, 11:52
Danke für alle Rückmeldungen und Anregungen.

@TiGü: Sowas habe ich befürchtet. Statt einem einfachen Zugriff muss ich dann im Getter auf den Parent, Owner, Monster ... zugreifen. Wird dann beim Debuggen etwas mühsamer. Aber vermutlich noch die beste Lösung.

@Günther: Ich schrieb bereits: "Nein - Datenhaltung in TElement kommt nicht in Frage". Die Daten sind in TMonster und dort sogar nur über virtuelle Getter verfügbar. Wenn dann das TElement die Daten liefern soll, dann muss es auf TMonster zugreifen oder von dort die Daten bekommen. Das entspräche auch dem von Dir erwähnten Callback/Event/OnChange. Im Übrigen sind es wohl nur Lesezugriffe.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#5

AW: Hilfklasse

  Alt 25. Mai 2022, 14:08
Den Owner braucht man nur, wenn die ParentComponent die SubKomponenten automatisch freigeben soll (ohne manuelles Free),
oder wenn die SubKomponenten auf die übergeordnete Komponente zugreifen müssen. (z.B. bei Zuweiseung Daten dort ändern oder Notifications/OnChangeEvents dort auslösen)

Die Freigabe kann/wird hier über die Referenzzählung des Interfaces erledigt. (FElement ist ja ein IElement und kein TElement)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Hilfklasse

  Alt 25. Mai 2022, 15:30
Wenn die Struktur des IMonster-Interface und die zugrunde liegenden Klassen nicht verändert werden können, bau eine Fassade, die deinem Anwendungsfall gerecht wird.
Delphi-Quellcode:
unit Fassade;

interface

uses
  Graphics;

type
  TTyp = (Kreis, Quadrat);

  IMonster = interface(IInterface)
    function GetElementTyp: TTyp;
    function GetElementFarbe: TColor;
    function GetElementGroesse: Double;
    function GetReferenzTyp: TTyp;
    function GetReferenzFarbe: TColor;
    function GetReferenzGroesse: Double;
    {...}
    property ElementTyp: TTyp read GetElementTyp;
    property ElementFarbe: TColor read GetElementFarbe;
    property ElementGroesse: Double read GetElementGroesse;
    {...}
    property ReferenzTyp: TTyp read GetReferenzTyp;
    property ReferenzFarbe: TColor read GetReferenzFarbe;
    property ReferenzGroesse: Double read GetReferenzGroesse;
    {...}
  end;

  IElement = interface(IInterface)
    function GetTyp: TTyp;
    function GetFarbe: TColor;
    function GetGroesse: Double;
    {...}
    property Typ: TTyp read GetTyp;
    property Farbe: TColor read GetFarbe;
    property Groesse: Double read GetGroesse;
  end;

  IMonsterFassade = interface(IInterface)
    function GetElement: IElement;
    function GetReferenz: IElement;
    {...}
    property Element: IElement read GetElement;
    property Referenz: IElement read GetReferenz;
  end;

  TMonsterReferenz = class(TInterfacedObject)
    constructor Create(AParent: IMonster);
    destructor Destroy; override;
  protected
    FParent: IMonster;
  end;

  TElement = class(TMonsterReferenz, IElement)
    function GetTyp: TTyp;
    function GetFarbe: TColor;
    function GetGroesse: Double;
  end;

  TReferenz = class(TMonsterReferenz, IElement)
    function GetTyp: TTyp;
    function GetFarbe: TColor;
    function GetGroesse: Double;
  end;

  TMonsterFassade = class(TMonsterReferenz, IMonsterFassade)
    constructor Create(AParent: IMonster);
    destructor Destroy; override;
  private
    FElement: IElement;
    FReferenz: IElement;
  public
    function GetElement: IElement;
    function GetReferenz: IElement;
  end;

implementation


{ TMonsterReferenz }

constructor TMonsterReferenz.Create(AParent: IMonster);
begin
  inherited;
  FParent := IMonster;
end;

destructor TMonsterReferenz.Destroy;
begin
  FParent := nil;
  inherited;
end;

{ TElement }

function TElement.GetFarbe: TColor;
begin
  Result := FParent.GetElementFarbe
end;

function TElement.GetGroesse: Double;
begin
  Result := FParent.GetElementGroesse;
end;

function TElement.GetTyp: TTyp;
begin
  Result := FParent.GetElementTyp;
end;

{ TReferenz }

function TReferenz.GetFarbe: TColor;
begin
  Result := FParent.GetReferenzFarbe
end;

function TReferenz.GetGroesse: Double;
begin
  Result := FParent.GetReferenzGroesse;
end;

function TReferenz.GetTyp: TTyp;
begin
  Restlt := FParent.GetReferenzTyp;
end;

{ TMonsterFassade }

constructor TMonsterFassade.Create(AParent: IMonster);
begin
  inherited;
  FElement := TElement.Create(AParent);
  FReferenz := TReferenz.Create(AParent);
end;

destructor TMonsterFassade.Destroy;
begin
  FElement := nil,
  FReferenz := nil,
  inherited;
end;

function TMonsterFassade.GetElement: IElement;
begin
  Result := FElement;
end;

function TMonsterFassade.GetReferenz: IElement;
begin
  Result := FReferenz;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.993 Beiträge
 
Delphi 12 Athens
 
#7

AW: Hilfklasse

  Alt 25. Mai 2022, 17:04
Wenn die Getter schon passend in TMonster vorhanden sind, dann kannst du es ja auch mal so versuchen:
Delphi-Quellcode:
type
  TTyp = (Kreis, Quadrat);

type
  IElement = interface
    function GetFarbe: TColor;
    function GetGroesse: Double;
    function GetTyp: TTyp;
    property Typ: TTyp read GetTyp;
    property Farbe: TColor read GetFarbe;
    property Groesse: Double read GetGroesse;
  end;

  IReferenz = interface(IElement)
  end;

  IMonster = interface
    function GetElement: IElement;
    function GetReferenz: IReferenz;
    property Element: IElement read GetElement;
    property Referenz: IReferenz read GetReferenz;
  end;

type
  TMonster = class(TInterfacedObject, IMonster, IElement, IReferenz)
    function IElement.GetFarbe = GetElementFarbe;
    function IElement.GetGroesse = GetElementGroesse;
    function IElement.GetTyp = GetElementTyp;
    function IReferenz.GetFarbe = GetReferenzFarbe;
    function IReferenz.GetGroesse = GetReferenzGroesse;
    function IReferenz.GetTyp = GetReferenzTyp;
  private
    function GetElement: IElement;
    function GetReferenz: IReferenz;
    function GetElementFarbe: TColor;
    function GetElementGroesse: Double;
    function GetElementTyp: TTyp;
    function GetReferenzFarbe: TColor;
    function GetReferenzGroesse: Double;
    function GetReferenzTyp: TTyp;
  end;

{ TMonster }

function TMonster.GetElement: IElement;
begin
  Result := Self as IElement;
end;

function TMonster.GetReferenz: IReferenz;
begin
  Result := Self as IReferenz;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.378 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Hilfklasse

  Alt 27. Mai 2022, 09:42
Hallo zusammen,
Danke nochmals für alle Vorschläge. Klar ist auf jeden Fall dass "nimm das Brett vor Deinem Kopf und machs einfach so" nicht geht.

Ich mach mich mal ran und versuche was so ähnlich wie Eure Vorschläge. Das IMonster-Interface und die zugrunde liegenden Klassen kann (und will) ich schon ändern, halt nur nicht so, dss die Daten nicht mehr von dort kommen. Vielleicht kann ich auf den Wrapper verzichten.

Passieren muss auf jeden Fall was. IMonster hat 95 properties, dazu noch viele Einzel-Methoden und noch Nachfahren die noch vieles zu nehmen.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.993 Beiträge
 
Delphi 12 Athens
 
#9

AW: Hilfklasse

  Alt 30. Mai 2022, 13:52
Ich habe meinen Vorschlag nochmal überarbeitet. Das IReferenz Interface wird eigentlich nur für die Method Resolution Clause und in GetReferenz verwendet und muss somit gar nicht öffentlich sein.

Mit diesem Ansatz muss also nur die Implementierung entsprechend formuliert werden. Zusätzliche Hilfsklassen sind nicht notwendig.
Delphi-Quellcode:
type
  TTyp = (Kreis, Quadrat);

type
  IElement = interface
    function GetFarbe: TColor;
    function GetGroesse: Double;
    function GetTyp: TTyp;
    property Typ: TTyp read GetTyp;
    property Farbe: TColor read GetFarbe;
    property Groesse: Double read GetGroesse;
  end;

  IMonster = interface
    function GetElement: IElement;
    function GetReferenz: IElement;
    property Element: IElement read GetElement;
    property Referenz: IElement read GetReferenz;
  end;
Delphi-Quellcode:
type
  IReferenz = interface(IElement)
  end;
  
TMonster = class(TInterfacedObject, IMonster, IElement, IReferenz)
    function IElement.GetFarbe = GetElementFarbe;
    function IElement.GetGroesse = GetElementGroesse;
    function IElement.GetTyp = GetElementTyp;
    function IReferenz.GetFarbe = GetReferenzFarbe;
    function IReferenz.GetGroesse = GetReferenzGroesse;
    function IReferenz.GetTyp = GetReferenzTyp;
  private
    function GetElement: IElement;
    function GetReferenz: IElement;
    function GetElementFarbe: TColor;
    function GetElementGroesse: Double;
    function GetElementTyp: TTyp;
    function GetReferenzFarbe: TColor;
    function GetReferenzGroesse: Double;
    function GetReferenzTyp: TTyp;
  end;

{ TMonster }

function TMonster.GetElement: IElement;
begin
  Result := Self as IElement;
end;

function TMonster.GetReferenz: IElement;
begin
  Result := Self as IReferenz;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  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 09:42 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