Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi "Fehler" bei Überschreiben von Properties (https://www.delphipraxis.net/85851-fehler-bei-ueberschreiben-von-properties.html)

3_of_8 5. Feb 2007 21:28


"Fehler" bei Überschreiben von Properties
 
Morgen.

Ich habe gerade eine recht... seltsame Entdeckung bei der Überschreibung von Properties gemacht.

Es sieht so aus, als würde der Compiler sich gar nicht erst überlegen, ob er die Property der Oberklasse oder die der Unterklasse nimmt. Ich kann das Vorgehen des Compilers zwar verstehen, aber eigentlich müsste er doch bei einer Situation wie der in meinem Testprojekt einen eigenen Eintrag in der VMT anlegen und dann da nachschauen... :gruebel:

Folgende Klassen:
Delphi-Quellcode:
type
  TA=class
  protected
    FFoo: Integer;
  public
    property Foo: Integer read FFoo write FFoo;
  end;

  TB=class(TA)
  public
    procedure SetFoo(AFoo: Integer);
    property Foo: Integer read FFoo write SetFoo;
  end;

implementation

procedure TB.SetFoo(AFoo: Integer);
begin
  FFoo:=AFoo;
  showmessage('Wuppdi');
end;
Jetzt folgender Code:

Delphi-Quellcode:
var a: TB;
begin
  a:=TB.Create;
  a.Foo:=42;
end;
Es kommt wie erwartet die Messagebox. Kleine Änderung:

Delphi-Quellcode:
var a: TA;
begin
  a:=TB.Create;
  a.Foo:=42;
end;
Keine Messagebox. Der Compiler beschreibt einfach FFoo und ruft SetFoo nicht auf.

Mich würde auch interessieren, ob sich das bei neueren Delphiversionen reproduzieren lässt.

mkinzler 5. Feb 2007 21:41

Re: "Fehler" bei Überschreiben von Properties
 
Du hast zwar ne Instanz von TB erzeugt, diese wird aber einer Referenzvariable für TA zuhewiesen, deshalb wird auch die Implementierung von TA verwendet.

Hawkeye219 5. Feb 2007 21:49

Re: "Fehler" bei Überschreiben von Properties
 
Hallo Manuel,

VMT = Virtual Method Table :wink:

Wo hast du eine virtuelle Methode?

Gruß Hawkeye

3_of_8 5. Feb 2007 21:56

Re: "Fehler" bei Überschreiben von Properties
 
Das ist es ja: Die soll der Compiler implizit anlegen. Sinngemäß würde ich sagen: Wenn ich die Property in der Unterklasse überschreibe und eine Instanz dieser Unterklasse habe, dann soll der Compiler auch die überschriebene Property aufrufen.

mkinzler 5. Feb 2007 21:58

Re: "Fehler" bei Überschreiben von Properties
 
Die Variable ist aber vom Typ der Oberklasse.

3_of_8 5. Feb 2007 22:01

Re: "Fehler" bei Überschreiben von Properties
 
Ja, aber die Instanz ist eine Instanz der Unterklasse. Nur der Instanzenpointer ist halt als Pointer auf die Instanz der Oberklasse deklariert.

Für mich ist es leicht sinnlos, wenn TB(a).Foo:=42; ein anderes Ergebnis bringt als a.Foo:=42.

EDIT: Mir ist klar, dass das kein Bug ist, sondern "as designed", aber ich halte das trotzdem für nicht OOP-konzeptgemäß.

JasonDX 5. Feb 2007 22:27

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Zitat von 3_of_8
ich halte das trotzdem für nicht OOP-konzeptgemäß.

Ist es aber. Alle Aufrufe von Members, welche keinen Eintrag in der VMT haben, werden von der Klasse aufgerufen, unter der die Variable deklariert, nicht instanziert wurde.
Einfach aus dem Grund, weil ansonsten zur Compile-Time nicht entschieden werden kann, welche Methode ausgefuehrt werden soll.

greetz
Mike

3_of_8 5. Feb 2007 22:37

Re: "Fehler" bei Überschreiben von Properties
 
Das ist mir klar. Deswegen sagte ich ja auch, der Compiler soll in diesem Fall einen VMT-Eintrag anlegen, damit er es weiß.

Elvis 5. Feb 2007 22:41

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Zitat von 3_of_8
Das ist mir klar. Deswegen sagte ich ja auch, der Compiler soll in diesem Fall einen VMT-Eintrag anlegen, damit er es weiß.

Delphi kennt keine virtuellen Properties.
Case closed. ;)

3_of_8 5. Feb 2007 22:44

Re: "Fehler" bei Überschreiben von Properties
 
Klar. Aber Delphi kennt virtuelle Methoden, also könnte der Compiler einen virtuellen Setter anlegen anstatt das "write FFoo" wörtlich zu nehmen. Ich habe jedenfalls relativ lange gebraucht, um diesen Fehler zu finden, vor allem deshalb, weil ich an der falschen Stelle gesucht habe. Ich habe mir gedacht "ich habe hier die Property überschrieben, also passt das" und habe Hunderte andere Codezeilen und Tutorials und Beispielunits durchwühlt.

Naja, ich glaube in Zukunft deklariere ich immer Settermethoden für Properties, die überschrieben werden.

JasonDX 5. Feb 2007 22:47

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Zitat von 3_of_8
Deswegen sagte ich ja auch, der Compiler soll in diesem Fall einen VMT-Eintrag anlegen, damit er es weiß.

Warum sollte er einen Eintrag dafuer erstellen? Nix is als virtual deklariert, nix kommt in die VMT. Wenn du willst, dass getter und setter von Kindklassen ueberschrieben werden koennen sollen, dann erstelle sie von Anfang an, und deklariere sie als Virtual.
Ich wuerde den Compiler zu Tode pruegeln, wenn er mir eine virtuelle Setter-Methode deklarieren wuerde, obwohl ich einen Direkten Zugriff von der Property auf die Variable wuensche.

greetz
Mike

3_of_8 5. Feb 2007 22:50

Re: "Fehler" bei Überschreiben von Properties
 
Ich meinte ja auch, er solle es nur tun, wenn man ansonsten Ärger mit den überschriebenen Properties bekommt.

Wie gesagt, es ist für mich äußerst... befremdlich/seltsam/gewohnheitsbedürftig, dass TB(a).Foo:=42 etwas anderes bewirkt als a.Foo:=42. Intuitiv würde ich sagen, das widerspricht der "dynamischen Bindung", wenn man so verschiedene Effekte durch Typencasting bei Klassen erreicht.

JasonDX 5. Feb 2007 22:57

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Zitat von 3_of_8
Ich meinte ja auch, er solle es nur tun, wenn man ansonsten Ärger mit den überschriebenen Properties bekommt.

Nein, das wuerde zu noch inkonsistenterem Verhalten fuehren.

Zitat:

Zitat von 3_of_8
Intuitiv würde ich sagen, das widerspricht der "dynamischen Bindung", wenn man so verschiedene Effekte durch Typencasting bei Klassen erreicht.

Wenn an deiner Property irgendetwas "dynamisches" dabeiwaere, waere es auch irgendwie widersprechend, aber es is nunmal nix "dynamisch"/"virtuell" deklariert, womit eine solche Verhaltensaenderung durch Typecasts durchaus nachvollziehbar, logisch und beabsichtigt ist. ;)

greetz
Mike

3_of_8 6. Feb 2007 13:17

Re: "Fehler" bei Überschreiben von Properties
 
*kratz*

Naja egal. Welche Workaround gibt es da? Einfach die Property in der Oberklasse statt mit Direktzugriff auf die Felder mit einem Setter deklarieren?

igel457 6. Feb 2007 13:28

Re: "Fehler" bei Überschreiben von Properties
 
Also ich mache das normalerweise so:
Delphi-Quellcode:
type
  TA=class
  protected
    FFoo: Integer;
    function GetFoo: Integer;virtual;
    procedure SetFoo(AFoo: Integer);virtual;
  public
    property Foo: Integer read GetFoo write SetFoo;
  end;

  TB=class(TA)
  protected
    procedure SetFoo(AFoo: Integer);override;
    function GetFoo: Integer;override;
  public
  end;

implementation

procedure TA.SetFoo(AFoo: Integer);
begin
  FFoo := AFoo;
end;

procedure TA.SetFoo(AFoo: Integer);
begin
  Result := FFoo;
end;

procedure TB.SetFoo(AFoo: Integer);
begin
  FFoo := AFoo;
  ShowMessage('BLA');
end;

procedure TB.SetFoo(AFoo: Integer);
begin
  Result := FFoo div 2;
end;
[edit]Ausversehen auf Absenden gekommen...[/edit]
[edit]Noch einen Fehler gefunden[/edit]

mkinzler 6. Feb 2007 13:29

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Naja egal. Welche Workaround gibt es da? Einfach die Property in der Oberklasse statt mit Direktzugriff auf die Felder mit einem Setter deklarieren?
Wäre ne Option.

Der_Unwissende 6. Feb 2007 18:29

Re: "Fehler" bei Überschreiben von Properties
 
Zitat:

Zitat von 3_of_8
Ich meinte ja auch, er solle es nur tun, wenn man ansonsten Ärger mit den überschriebenen Properties bekommt

Hi,
mal nebenbei bemerkt, Du überschreibst hier nichts, Du verdeckst nur. Das liegt eben daran, dass Delphi standardmässig statisch bindet. Wollte ich nur mal anmerken, denn beim Überschreiben hättest Du schon irgendwie dein erwartetes Verhalten.

Gruß Der Unwissende


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:38 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