![]() |
Interfaces, Verwenden von Gettern
Hallo zusammen,
mir fällt beim Testen Folgendes in den FMX Sourcen auf:
Delphi-Quellcode:
Ich würde im Design oben IMMER den entsprechenden Getter verwenden, auch bei C.).
IBrushObject = interface(IFreeNotificationBehavior)
['{BB870DB6-0228-4165-9906-CF75BFF8C7CA}'] function GetBrush: TBrush; // A.) Hier wird ein Getter vorausgesetzt property Brush: TBrush read GetBrush; end; TBrushObject = class(TFmxObject, IBrushObject) private FBrush: TBrush; { IBrushObject } function GetBrush: TBrush; // B.) Der Getter wird hier definiert, Result := FBrush; protected procedure SetName(const NewName: TComponentName); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Brush: TBrush read FBrush write FBrush; // C.) Hier wird direkt auf das Feld zugegriffen end; Jetzt frage ich mich ob die EMBA C.) Variante evtl. irgendeinen einen Vorteil hat ? (Ist vielleicht schneller, weil inline und der Getter entfällt). Ist C.) überhaupt ein sauberes Klassendesign ? Meiner Meinung nach eher nicht, weil es zwei Arten des Zugriffs gibt. Rollo |
AW: Interfaces, Verwenden von Gettern
Der Getter bringt hier m.M. nach keinen Vorteil.
|
AW: Interfaces, Verwenden von Gettern
Ich kann mir nicht vorstellen, dass da ein Konzept oder Plan dahinter steckt.
Ehrlich hätte ich erwartet, dass der Compiler das gar nicht akzeptiert. Ich halte das für unsauberen Code. Selbst wenn das eine halbe Millisekunde spart wiegt das nicht die Probleme auf, die eine solche Unordnung möglicherweise schafft. |
AW: Interfaces, Verwenden von Gettern
Warum sollte der Compiler das nicht akzeptieren? Ist eine "normale" Funktion und eine Property mit Direktzugriff auf die private Variable. Aus dem Namen könnte man die Absicht ableiten, der Compiler aber nicht.
|
AW: Interfaces, Verwenden von Gettern
Zitat:
Zitat:
Zitat:
Folgendes Szenario wäre hypothetisch denkbar: Nehmen wir an, das Feld wäre nil, dann würde das so auch in der DFM/FMX gespeichert und auch so wieder gelesen. Der Getter könnte in diesem Fall aber automatisch eine Default-Instanz erzeugen, damit der nil-Fall bei Interface-Zugriff niemals auftritt. Würde das Property immer den Getter verwenden, würde die Default-Instanz in der DFM/FMX gespeichert und wäre somit nicht mehr default. |
AW: Interfaces, Verwenden von Gettern
Das ist mal wieder der Tatsache geschuldet, dass Properties in Delphi technisch nur halbherzig eine Kapselung darstellen.
Aus OOP und Codesicht habe ich durch eine Eigenschaft in Delphi eine Kapselung hergestellt - also wenn ich auf der konsumierenden Seite auf eine Eigenschaft zugreife, dann kann ich in der implementierenden Klasse, direkt auf die Feldvariable oder über einen Setter wer weiß was machen, ohne dass davon die konsumierende Seite etwas mitbekommen muss oder ich Code anpassen muss. ABER: Durch die Art der Implementierung (auf der konsumierenden Seite baut der Compiler entsprechenden Code je nachdem ob hinter der Eigenschaft direkt die Feldvariable steht oder ein Getter) ergibt sich die zuvor erwähnte halbherzige Kapselung. Die aus OOP Sicht eine nonbreaking change darstellende Änderung von direktem Feldzugriff auf Setter bedeutet in Delphi tatsächlich technisch (in den Binaries) einen breaking change, da jede Stelle, die in einem solchen Fall lesend auf die Eigenschaft zugreift, neu kompiliert werden muss. Das ist übrigens ebenfalls so, wenn ich den Getter plötzlich als virtual markiere - auch hier erzeugt das einen breaking change für die aufrufende Stelle. |
AW: Interfaces, Verwenden von Gettern
Hallo Stevie,
guter Hinweis, danksehr. Hallo Uwe, Zitat:
Dann werde ich da wohl nach wie vor bevorzugt dizipliniert über Getter/Setter drauf zugreifen. Rollo |
AW: Interfaces, Verwenden von Gettern
Zitat:
Du verbindest die Funktion GetBrush ja nur deswegen mit dem Property Brush, weil es die übliche Namensgebung ist. Aus Compilersicht ist GetBrush aber nur die Implementierung des Interfaces. Sollte der Compiler in diesem Fall etwas verbieten oder erzwingen, fände ich das schon eine gewisse Einschränkung. |
AW: Interfaces, Verwenden von Gettern
Hallo Uwe,
das ist ja richtig, wenn es korrekt implementiert wrd. Mir geht es aber in erster Linie darum das ich das bekomme was ich erwarte. Und so eine Getter könnte z.B. auch ungewollte Seiteneffekte haben, also hättee ich mit/ohne Interface unterschiedliches Verhalten bei so einer "simplen" Property. Naja, schon die TBrush könnte in verschiedenen Ableitungen daherkommen, davon mal abgesehen. Ich vermeide gerne solche Seiteneffekte und Redundanzen in dem ich möglichst immer die gleichen Routinen verwende, auch wenn es vielleicht manchmal lästig und überflüssig ist. Das Umbiegen von Methoden kann natürlich auch einen Zweck haben und etwas ganz anderes zurückliefern, aber in der Regel erwarte ich dann bei solchen Klassen dann auch das ich etwas Anderes bekommen kann. Ich versuche meistend den Code so zu halten das ich auch in 6 Monaten direkt noch weiss was eine Methode bewirkt, ohne erst tiefer reinschauen zu müssen. Dabei möglichst sprechende Namen verwenden, auch wenn sie recht lang werden können. Möglichst geradlinig ohne Seiteneffekte und Fettnäpfchen, das meine ich mit WYSIWYG. Leider gelingt mir das aber nicht immer :oops: Wenn ich aber GetBrush, GetSize, o.ä. sehe, bei relativ simplen Klassen, dann erwarte ich eigentlich das es keine zwei Wege gibt ohne besonderen Nutzen. Rollo |
AW: Interfaces, Verwenden von Gettern
Zitat:
Was mich in diesem Fall die Augenbrauen hochziehen ließ, war die Bemerkung: Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:10 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