AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Class helper wird übersprungen wenn...

Ein Thema von Der schöne Günther · begonnen am 16. Okt 2014 · letzter Beitrag vom 17. Okt 2014
Antwort Antwort
Der schöne Günther

Registriert seit: 6. Mär 2013
6.156 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Class helper wird übersprungen wenn...

  Alt 16. Okt 2014, 20:33
Delphi-Version: 5
Properties im Spiel sind.

Beispiel: Ich schreibe einen Helfer für eine getValue(): Integer -Funktion. Fügt eine Unterklasse oder ein passendes Interface nun eine Property Value: Integer ein, bekommt man über diese Property immer den reinen Getter, ohne die Hilfsfunktion!

Folgende Typen
Delphi-Quellcode:
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;
erzeigen unsinnigerweise folgende Ausgabe:
Code:
   WriteLn( TSomeClass.Create().Value ); // 84
   WriteLn( TSubClass.Create().Value ); // 42

Kann ich etwas dagegen tun oder nur weinen?

Meine Intention war die Methode SetNodeValue(OleVariant) von TXMLNode zu patchen. Und das ruft man üblicherweise über die Property NodeValue von IXMLNode auf.
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Class helper wird übersprungen wenn...

  Alt 16. Okt 2014, 20:42
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.
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Class helper wird übersprungen wenn...

  Alt 16. Okt 2014, 21:03
Meine Intention war die Methode SetNodeValue(OleVariant) von TXMLNode zu patchen. Und das ruft man üblicherweise über die Property NodeValue von IXMLNode auf.
Class Helper wirken nicht auf Interfaces. Dein Beispiel trifft leider nicht dein Problem.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Class helper wird übersprungen wenn...

  Alt 16. Okt 2014, 21:09
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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (16. Okt 2014 um 21:13 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#5

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 05:19
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:
Type
  TMemoHelper = Class Helper for TMemo
  public
    Procedure Writeln (const text : String);
  end;
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.

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.
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.156 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 10:24
Ich verstehe ausnahmsweise bei keinem von euch, was er mir sagen will

Ich stelle noch einmal dar was ich meinte:
  • Man setze einen Class Helper ein der einen Getter ersetzt/verändert. Alles funktioniert wie gewohnt. Ist der Helper im Scope, werden seine Dinge genommen.
  • Man führt in der Klasse eine Property ein welche den normalen Getter benutzt
  • Fragt man nun die Property ab bekommt man den "unbeholfenen" Getter obwohl der Class Helper im Gültigkeitsbereich ist
.

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.

Geändert von Der schöne Günther (17. Okt 2014 um 10:28 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 10:39
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.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  R: TRect;
behin
  R := irgendwas;
  with R do
    {Self.}Width := Right - Left;
end;
Jetzt ratet mal, was die "neueren" Records für nette Hilfsfunktionen besitzen und warum der Code so jetzt nicht mehr geht.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.156 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 10:57
Kein Augenrollen, das ist auch gut so. Allen die with benutzen kann man das Leben nicht schwer genug machen!
Das ist der "expert"-Modus von Delphi.
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

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

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 13:27
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 schon vorhandene Methoden verdecken. Dass die Helper in Delphi das können, ist eher nen Designfehler (ein manchmal nützlicher muss ich zugeben).

Willst du nun auch, dass der Helper auch explizit für TSubClass funktioniert, dann musst du auch einen expliziten Helper schreiben.

Delphi-Quellcode:
  TSubClassHelper = class helper(TSomeClassHelper) for TSubClass
  end;
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.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (17. Okt 2014 um 13:38 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Class helper wird übersprungen wenn...

  Alt 17. Okt 2014, 13:37
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.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  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 10:54 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