![]() |
Fluent Design und Records
Liebe Delphi-Gemeinde,
ich mag im Design meiner Objekte das Pattern des Fluent Design sehr gerne und gestalte meine Methoden deshalb gerne damit. Ich meine damit also etwa ein solches Gebilde:
Delphi-Quellcode:
Result := CreateSomeInterface.DoSomething('withParameter').DoSomethingOther.ConvertEverythingToString;
Das ist an manchen Stellen sehr praktisch und macht den Code in meinen Augen etwas schöner, vor allem, wenn man mit Interfaces statt mit Objekten arbeitet. Nun frage ich mich, ob man das auch mit Records machen kann, bzw. ob das sinnvoll ist. Angenommen ich habe folgendes:
Delphi-Quellcode:
Soweit ich das verstehe, würde das
type
Tfluent = record variable: string; function DoSomething(const mParameter: string): Tfluent; end; function Tfluent.DoSomething(const mParameter: string): Tfluent; begin variable := variable + mParameter; Result := Self; end;
Delphi-Quellcode:
bei Records immer dazu führen, dass der komplette Record kopiert wird, da eine Übergabe bei Records ja "als Wert" und nicht "als Zeiger" funktioniert.
Result := Self;
Damit wäre das Fluent Design bei Records nicht sinnvoll und würde ständig eine Kopiererei der Daten verursachen. Ist das so, oder gibt es einen Trick? Wie macht ihr das? Ich fände die Records deshalb sehr schön, weil man z.B. mit Operator Overloading sich dann eine Methode "ConvertEverthingToString" sparen könnte, was meines Wissens mit Objekten/Interfaces bislang noch nicht geht. Viele Grüße Harald |
AW: Fluent Design und Records
Man kann einen Record erstellen, der als einzige Methoden Konstruktoren hat. Das ist natürlich Quatsch, würde aber vielleicht funktionieren. Ich setze schon mal einen Helm auf, weil ich gleich gesteinigt werde.
|
AW: Fluent Design und Records
Du könntest jeweils einen Zeiger auf Self zurückgeben. Also Result := @Self (mit Klammeraffe).
Da Delphi erlaubt, beim Dereferenzieren den ^ wegzulassen, könnten die Aufrufe sogar identisch ausschauen. (Wobei ich dieses Feature persönlich verabscheue. Aber die Geschmäcker sind verschieden.) |
AW: Fluent Design und Records
Eigentlich hat uligerhardt schon alles gesagt...
Ich würde jedoch das ^ nie weglassen... Einfach um den Ursprung besser zu verstehen. |
AW: Fluent Design und Records
Zitat:
|
AW: Fluent Design und Records
|
AW: Fluent Design und Records
Zitat:
Und vielen Dank auch an alle, die sich bisher beteiligt hatten. Hmmm, das mit der Adresse und dem ^ ist eine Lösung, aber irgendwie mag ich solche Operatoren in meinem normalen Code nicht - das sieht für mich immer nach Eingriff auf unterster Ebene aus. Und das ist in einer Bibliothek ok, aber für den täglichen Gebrauch... Ob ich dann wohl doch lieber bei den Interfaces bleibe? Viele Grüße Harald |
AW: Fluent Design und Records
Zitat:
|
AW: Fluent Design und Records
Hallo Zusammen,
jetzt habe ich den Vorschlag von uligerhardt mal ausprobiert, aber irgendwas scheine ich nicht richtig zu verstehen. Könnt Ihr mir nochmal weiterhelfen? Also, ich hab mal folgende Unit gemacht:
Delphi-Quellcode:
Testen wollte ich das Ganze so:
unit hs.str2;
interface type ThsStr2 = record FStr: string; function AsString: string; function Init(const mString: string): ThsStr2; end; implementation uses System.SysUtils; { ThsStr2 } function ThsStr2.AsString: string; begin Result := FStr; end; function ThsStr2.Init(const mString: string): ThsStr2; begin FStr := mString; // Result := @Self; // so war der Vorschlag, aber das kompiliert gar nicht "Pointer und ThsStr2" Result := ThsStr2(@Self); // so kompiliert es, aber wirft eine AV bei der Ausführung end; end.
Delphi-Quellcode:
Aber eben beim Init bekomme ich eine AV. Was mache ich falsch - oder wo ist mein Denkfehler?
procedure Test;
var lStr: ThsStr2; lDummy: string; begin lDummy := lStr.Init('dummy').AsString; end; Viele Grüße Harald |
AW: Fluent Design und Records
Sorry, ich hab's etwas kurz erklärt. :oops:
Du musst einen Zeigertyp zurückgeben, also etwas so:
Delphi-Quellcode:
type
PhsStr2 = ^ThsStr2; // Zeiger auf ThsStr2 ThsStr2 = record FStr: string; function AsString: string; function Init(const mString: string): PhsStr2; // <== Beachte den Rückgabetyp! end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:25 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 by Thomas Breitkreuz