AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Recordhelper - Methode mit gleichem Namen wie im Record
Thema durchsuchen
Ansicht
Themen-Optionen

Recordhelper - Methode mit gleichem Namen wie im Record

Ein Thema von Neutral General · begonnen am 23. Jul 2018 · letzter Beitrag vom 23. Jul 2018
Antwort Antwort
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:07
Delphi-Version: 10 Seattle
Hallo,

Das ist quasi eine Folgefrage zu TValue.AsVariant und Boolean - Fehler?
Da ich gerade (noch) nicht auf 10.2 umsteigen kann musste ich mir anders behelfen:
Delphi-Quellcode:
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;
Die markierte Zeile führt allerdings zu einer Endlosrekursion.
"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:
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;
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?
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
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:10
Delphi-Quellcode:
  else
    Result := inherited Self.AsVariant(); // !
end;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:12
Delphi-Quellcode:
  else
    Result := inherited Self.AsVariant(); // !
end;
"inherited" funktioniert in dem Zusammenhang nicht [...]
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:28
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;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:49
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;
Danke, so werd ichs machen!

Habe aber selbst noch etwas rumprobiert und auf Biegen und Brechen lässt es sich machen:
Delphi-Quellcode:
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;
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.
For Science und so.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 14:57
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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#7

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 16:13
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:
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;
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.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (23. Jul 2018 um 16:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Recordhelper - Methode mit gleichem Namen wie im Record

  Alt 23. Jul 2018, 16:35
Jain, aber du kannst aus der TypeInfo/RTTI den Zeiger der gewünschten Methode auslesen und diese dann direkt aufrufen, am Helper/Compiler vorbei.

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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  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 22:05 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