![]() |
Delphi-Version: 10 Seattle
Recordhelper - Methode mit gleichem Namen wie im Record
Hallo,
Das ist quasi eine Folgefrage zu ![]() Da ich gerade (noch) nicht auf 10.2 umsteigen kann musste ich mir anders behelfen:
Delphi-Quellcode:
Die markierte Zeile führt allerdings zu einer Endlosrekursion.
TValueHelper = record helper for TValue
public function AsVariant() : Variant; end; function TValueHelper.AsVariant: Variant; begin if (IsType<Boolean>()) then Result := AsBoolean() else Result := Self.AsVariant(); // ! end; "inherited" funktioniert in dem Zusammenhang nicht und auch sonst habe ich keine Art gefunden wie ich das original TValue.AsVariant aufrufen kann. Mein letzter und extremster Versuch:
Delphi-Quellcode:
Aber selbst in diesem Fall springt er wieder in den TValueHelper.AsVariant. Bedeutet das, dass das original-TValue.AsVariant nicht mehr existiert und nicht nur überdeckt sondern ersetzt wurde?
function TValueHelper.AsVariant: Variant;
var originalAsVariant: function(Self: TValue): Variant; begin originalAsVariant := @TValue.AsVariant; if (IsType<Boolean>()) then Result := AsBoolean() else Result := originalAsVariant(Self); end; Denn so sieht es für mich momentan aus. Die Frage ist nun: Existiert die ursprüngliche Methode noch und wenn ja, wie kann ich sie aufrufen? Disclaimer: Mir ist klar, dass ich das ganze umgehen kann, indem ich meine Helper-Methode einfach umbenenne, aber einerseits wäre mir ein Überdecken lieber und andererseits bin ich jetzt neugierig was da jetzt im Hintergrund wirklich passiert :shock: |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Delphi-Quellcode:
:?:
else
Result := inherited Self.AsVariant(); // ! end; |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Zitat:
Zitat:
|
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Das mit dem inherited funktioniert bei records ja leider nicht. In diesem Fall kann man das aber umgehen:
Delphi-Quellcode:
function TValueHelper.AsVariant: Variant;
begin if (IsType<Boolean>()) then Result := AsBoolean() else Result := AsType<Variant>; end; |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Zitat:
Habe aber selbst noch etwas rumprobiert und auf Biegen und Brechen lässt es sich machen:
Delphi-Quellcode:
Deine Lösung ist natürlich deutlich besser/eleganter und werde die auch auf jeden Fall verwenden, aber man hat ja nicht immer das Glück, dass man so nen schönen Ausweg hat.
var
OriginalTValueAsVariant: Pointer = @TValue.AsVariant; // Muss VOR dem Recordhelper deklariert/zugewiesen werden type TValueHelper = record helper for TValue public function AsVariant() : Variant; end; function TValueHelper.AsVariant: Variant; type TAsVariantFunc = function(Self: TValue): Variant; begin if (IsType<Boolean>()) then Result := AsBoolean() else Result := TAsVariantFunc(OriginalTValueAsVariant)(Self); end; For Science und so. |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Jupp, vor dem Helper, da wo es noch nicht überschrieben ist, oder aus der TypeInfo/RTTI auslesen.
Aber es ist doch ein Bug, dass inherited nicht geht? Nja, aber stimmt schon, inherited wird hier auf den Vorfahren der Klasse und nicht auf den "Vorfahren" des Helpers gehen. Allergings ist es im Normalfall eine schlechte Idee eine bestehende Funktion mit den Helpern verdecken zu wollen. Es ist schwer zu erkennen ob/wann der Helper genommen wird oder das Original des Typs. Wäre es nicht toll, wenn die Helperbugs mal nach all den Jahren behoben werden? (vorallem mehrere Helper an einem Typ) |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Man kann das ja nicht immer so machen, wie in diesem Fall richtigerweise von Uwe vorgeschlagen.
Daher einfach ausnutzen, dass bei einer Redefinition eines Typs der helper nicht berücksichtigt wird
Delphi-Quellcode:
Natürlich darauf achten, dass TValue2 vor dem Helper definiert wird, dadurch kennt er unten beim Hardcast nicht die helper Methode und ruft die aus System.Rtti auf.
type
TValue2 = type TValue; TValueHelper = record helper for TValue public function AsVariant: Variant; end; function TValueHelper.AsVariant: Variant; begin if IsType<Boolean> then Result := AsBoolean else Result := TValue2(Self).AsVariant(); end; |
AW: Recordhelper - Methode mit gleichem Namen wie im Record
Jain, aber du kannst aus der TypeInfo/RTTI den Zeiger der gewünschten Methode auslesen und diese dann direkt aufrufen, am Helper/Compiler vorbei. :zwinker:
Und bei dieser Art des Override ist es halt manchmal ungünstig, dass es "unbemerkt" nur dann überschrieben/überdeckt wird, wenn der Helper sichtbar ist. Bei uns hatte ich mal TField.Value mit einem Helper überschrieben, da Value:=Null nicht bei allen TField-Nachfolgern "richtig" funktioniert. Aber nach anfänglichen Problemchen wurde es dann doch als "zusätzliches" Property implementiert und nicht als soeine Überladung des eigentlichen Value-Property.
Delphi-Quellcode:
type
TFieldHelper = class helper for TField private function GetAsValueNullable : Variant; procedure SetAsValueNullable(const NewValue : Variant); public {$REGION 'Documentation'} /// <summary> /// <para> /// Liest immer NULL, wenn das Feld NULL ist und setzt auch die NULL. /// </para> /// <para> /// siehe TWideMemoField.GetAsVariant ... macht aus NULL ein '',<br />aber TWideStringField belässt es als /// NULL, aber nur im Getter und nicht im Setter. /// </para> /// </summary> {$ENDREGION} property ValueNullable : Variant read GetAsValueNullable write SetAsValueNullable; {$REGION 'Documentation'} /// <summary> /// <para> /// Achtung: Value=Variant, aber bei IsNull liefert/setzt es oftmals keine NULL.<br />z.B. TWideMemoField macht /// dataus einen Leersting ''<br />siehe ValueNullable /// </para> /// <para> /// Achtung: Property TField.Value=Variant, aber TIntegerField.Value=Integer<br />Property wird der Vererbung /// überdeckt. /// </para> /// </summary> {$ENDREGION} //property Value; deprecated; // aus unerfindlichen Gründen meint der Compiler dass Variant, GetAsVariant und SetAsVariant nicht im Vorfahren existieren //property Value: Variant read GetAsVariant write SetAsVariant; deprecated; property Value: Variant read _GetAsVariant write _SetAsVariant; //deprecated 'BUGFIX: use ValueNullable if Value can contains NULL-Values'; end; function TFieldHelper.GetAsValueNullable: Variant; begin if IsNull then Result := Null else Result := Value; end; procedure TFieldHelper.SetAsValueNullable(const NewValue: Variant); begin if VarIsNull(NewValue) then Clear else Value := NewValue; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:38 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