![]() |
Delphi-Version: 5
Class helper wird übersprungen wenn...
Properties im Spiel sind.
Beispiel: Ich schreibe einen Helfer für eine
Delphi-Quellcode:
-Funktion. Fügt eine Unterklasse oder ein passendes Interface nun eine Property
getValue(): Integer
Delphi-Quellcode:
ein, bekommt man über diese Property immer den reinen Getter, ohne die Hilfsfunktion!
Value: Integer
Folgende Typen
Delphi-Quellcode:
erzeigen unsinnigerweise folgende Ausgabe:
TSomeClass = class
public function getValue(): Integer; // Ergibt 42 end; TSubClass = class(TSomeClass) property Value: Integer read getValue; end; TSomeClassHelper = class helper for TSomeClass public function getValue(): Integer; // Verdoppelt den Wert von getValue() public property Value: Integer read getValue; end;
Code:
WriteLn( TSomeClass.Create().Value ); // 84
WriteLn( TSubClass.Create().Value ); // 42 Kann ich etwas dagegen tun oder nur weinen? :cry: Meine Intention war die Methode
Delphi-Quellcode:
von
SetNodeValue(OleVariant)
Delphi-Quellcode:
zu patchen. Und das ruft man üblicherweise über die Property
TXMLNode
Delphi-Quellcode:
von
NodeValue
Delphi-Quellcode:
auf.
IXMLNode
|
AW: Class helper wird übersprungen wenn...
Du kannst mit einem Class-Helper nichts überschreiben. Wenn Du den Getter tauschen möchtest, müsstest Du die Methoden-Tabelle der Klasse patchen. Hallvard Vassbotn hat in seinem Blog einiges dazu geschrieben.
|
AW: Class helper wird übersprungen wenn...
Zitat:
|
AW: Class helper wird übersprungen wenn...
Oder anders ausgedrückt: Ein Class-Helper kann nur nachträglich erweitern, aber nichts überschreiben/ändern.
In deinem Fall wäre doch ein virtueller Getter mit späteren überschreiben besser? Und wenn der Getter (die Methode) virtuell ist, dann könnte man dein Vorhaben auch über die RTTI erledigen (TVirtualMethodInterceptor, wenn man die VMT nicht manuell manipulieren will) |
AW: Class helper wird übersprungen wenn...
Class Helper sind ziemlich gefährlich. Denn es ist durch den Blick in den Code einer Klasse (hier) nicht ersichtlich, was sie genau macht, denn es könnte ja irgendwo noch ein Class Helper verborgen sein. Schlimm genug von Borland, das es das Überschreiben/Ersetzen einer Methode durch Class Helper erlaubt.
Class Helper haben aber natürlich ihre Daseinsberechtigung, denn das *erweitern* von Klassen ist nicht nur praktisch, sondern lagert redundante Hilfsfunktionen eben in ... 'class helper' aus. Blödes Beispiel:
Delphi-Quellcode:
Die Writeln-Methode ist sehr praktisch, hat aber eigentlich in der reinen TMemo-Klasse nichts zu suchen, weil sie die Funktionalität der Klasse nicht erweitert, sondern nur eine handliche Abkürzung für 'Lines.Add(Text)' anbietet. Die VErwendung von 'WriteLn' spart Tipparbeit und Code und wenn später die Semantik von 'WriteLn' irgendwie noch erweitert werden soll (loggen z.B.) hat man gleich den richtigen Punkt (nämlich einen einzigen), wo man ansetzen kann.
Type
TMemoHelper = Class Helper for TMemo public Procedure Writeln (const text : String); end; Mit Class Helpern kann man seine Klasse alltagstauglich machen, ohne sie zu überladen. PS: Bitte zerpflückt das Beispiel nicht, denn es ist nur ein Beispiel. |
AW: Class helper wird übersprungen wenn...
Ich verstehe ausnahmsweise bei keinem von euch, was er mir sagen will :love:
Ich stelle noch einmal dar was ich meinte:
Der Grund: Die Property der Basisklasse weiß nichts vom Helper. Aufrufe auf die Property gehen direkt auf den Getter zu und überspringen die Hilfsmethode komplett. Hier noch einmal Futter für Quellcode-Freunde:
Delphi-Quellcode:
program Project6;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, ClassUnit in 'ClassUnit.pas', ClassHelperUnit in 'ClassHelperUnit.pas'; begin try WriteLn( TMyClass.Create().getValue() ); // Ergibt 99 WriteLn( TMyClass.Create().Value ); // Ergibt 42 except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; readln; end.
Delphi-Quellcode:
unit ClassUnit;
interface type TMyClass = class function getValue(): Integer; property Value: Integer read getValue; end; implementation function TMyClass.getValue(): Integer; begin Result := 42; end; end.
Delphi-Quellcode:
unit ClassHelperUnit;
interface uses ClassUnit; type TMyClassHelper = class helper for ClassUnit.TMyClass function getValue(): Integer; end; implementation function TMyClassHelper.getValue():Integer; begin Result := 99; end; end. Die Abhilfe wäre, im Klassenhelper die Property auch zu überschreiben. Also eigentlich die Lösung für Leute die alleine denken können und nicht gleich ein Forum überfluten. Das blöde daran ist nur, dass man gekniffen wird wenn eine Unterklasse (oder eben ein Interface) die Property erst einführt. Dann bekommt man das "unbeholfene" Verhalten ohne es wahrscheinlich zu ahnen. Gefährliche Sachen... Uwe hatte also von Anfang an recht, ich hätte gleich anfangen können zu weinen. Denn in meinem Fall führt das Interface die Property ein, die Klasse hat die nicht. Und in Delphi gibt es keine Interface-Helper. |
AW: Class helper wird übersprungen wenn...
Bei Class-Helpern, sollte man eben nie etwas überschreiben verdecken und wenn man es dennoch macht, dann ist man selber Schuld und muß genauso aufpassen, wie bei den bösen WITHs. :stupid:
Delphi-Quellcode:
Jetzt ratet mal, was die "neueren" Records für nette Hilfsfunktionen besitzen und warum der Code so jetzt nicht mehr geht. :roll:
procedure TForm1.Button1Click(Sender: TObject);
var R: TRect; behin R := irgendwas; with R do {Self.}Width := Right - Left; end; |
AW: Class helper wird übersprungen wenn...
Kein Augenrollen, das ist auch gut so. Allen die
Delphi-Quellcode:
benutzen kann man das Leben nicht schwer genug machen! :smile2:
with
Das ist der "expert"-Modus von Delphi. |
AW: Class helper wird übersprungen wenn...
Die Regel scheint hier zu sein, dass Member in einer Subklasse der "geholfenen" Klasse vorrang vor den Membern im Helper haben.
Das ergibt sich aber aus dem Typ der Variable auf den die Methode aufgerufen wird. Wenn man drüber nachdenkt, dann wird schon klar, warum das so ist: Wenn ich in einer abgeleiteten Klasse einen Member einführe, den es über den Class Helper der Basisklasse auch schon gibt, dann wird der implizit verdeckt. Hier hat man dafür entschieden, die Vererbung gegen den Helper gewinnen zu lassen, was durchaus nachvollziehbar ist. Die Extension Methods in C# können übrigens auf keinen Fall ![]() Willst du nun auch, dass der Helper auch explizit für TSubClass funktioniert, dann musst du auch einen expliziten Helper schreiben.
Delphi-Quellcode:
Eine saubere Lösung sähe allerdings eher so aus, den Member im Helper so zu nennen, dass er nicht mit in Subklassen eingeführten Membern kollidiert.
TSubClassHelper = class helper(TSomeClassHelper) for TSubClass
end; |
AW: Class helper wird übersprungen wenn...
Knackpunkt ist einfach, daß über ein Interface IXMLNode auf den Getter zugegriffen wird. Dessen Implementation liegt aber nun mal in TXMLNode und das kennt den Code des Class Helpers eben nicht.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:00 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