TypeCast - Problem

Rund um die LCL und andere Komponenten
TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

TypeCast - Problem

Beitrag von TBug »

Ich habe einige Komponenten, bei denen ich einige Properties "überschreibe".

Beispiel:

Code: Alles auswählen

 
type
  TMyEdit = class(TEdit)
   private
    FEnhReadOnly: Boolean;
    function GetEnhReadOnly(): Boolean; virtual;
    procedure SetEnhReadOnly(AValue: Boolean); virtual;
   public
    constructor Create(AOwner: TComponent); override;
   published
    property ReadOnly: Boolean read GetEnhReadOnly write SetEnhReadOnly;
  end;   
 

Code: Alles auswählen

 
constructor TMyEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEnhReadOnly := inherited ReadOnly;
end;
 
function TMyEdit.GetEnhReadOnly(): Boolean;
begin
  Result := FEnhReadOnly;
end;
 
procedure TMyEdit.SetEnhReadOnly(AValue: Boolean);
begin
  if (FEnhReadOnly <> AValue) then
   begin
    FEnhReadOnly := AValue;
   end;
end;   
 
Gibt es unter Lazarus die Möglichkeit bei einem TypeCast den Property-Wert der eigentlichen Komponente (TMyEdit) und nicht der Vorgänger-Komponente (TEdit) auszulesen?

Also wenn ich in diesem Beispiel

Code: Alles auswählen

MyEdit1.ReadOnly := true;
setze, dann bekomme ich mit

Code: Alles auswählen

lBoolean := (MyEdit1 as TEdit).ReadOnly;
für lBoolean der Wert "false" zurück statt wie zu erwarten wäre "true".

Bei einem HardCast

Code: Alles auswählen

lBoolean := TEdit(MyEdit1).ReadOnly;
wäre der Wert für lBoolean "false" hingegen in Ordnung und auch zu erwarten gewesen, aber nicht bei einem SoftCast.

Bug oder Feature ???


.

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: TypeCast - Problem

Beitrag von wp_xyz »

Ich würde im Setter auch das ReadOnly des Vorfahren setzen. Als Folge davon, wird das Feld FEnhReadOnly unnötig, denn im Getter kannst du den Wert vom Vorfahren abfragen:

Code: Alles auswählen

 
type
  TMyEdit = class(TEdit)
   private
    function GetReadOnly(): Boolean; virtual;
    procedure SetReadOnly(AValue: Boolean); virtual;
   published
    property ReadOnly: Boolean read GetReadOnly write SetReadOnly;
  end;   
 
function TMyEdit.GetReadOnly(): Boolean;
begin
  Result := inherited ReadOnly;
end;
 
procedure TMyEdit.SetReadOnly(AValue: Boolean);
begin
  inherited ReadOnly := AValue;
end;

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TypeCast - Problem

Beitrag von TBug »

wp_xyz hat geschrieben:Ich würde im Setter auch das ReadOnly des Vorfahren setzen. Als Folge davon, wird das Feld FEnhReadOnly unnötig, denn im Getter kannst du den Wert vom Vorfahren abfragen:
Genau das ist das Problem, dass in vielen Fällen meiner eigenen Komponenten eben NICHT der Vorfahr den Wert erhalten soll/darf. Vor allem seit ich angefangen habe mit Lazarus zu arbeiten wird dies aufgrund verschiedener Unzulänglichkeiten von Lazarus in verstärktem Maße leider notwendig.

Es geht bei der Frage nicht darum, wie man eine Property setzen kann, sondern warum der TypeCast nicht wie gewünscht/erwartet funktioniert und ob Lazarus hierfür eine Lösung (Compilerschalter?) bietet oder ob es einfach nur ein Bug ist.


.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TypeCast - Problem

Beitrag von Socke »

Du kannst die Get- und Set-Methoden überschreiben. Die Property selbst müsstest du nur überschreiben, wenn die originale property keine oder statische Methoden verwedent.

Code: Alles auswählen

 
type
  TMyEdit = class(TEdit)
   private
    FEnhReadOnly: Boolean;
    function GetEnhReadOnly(): Boolean; virtual;
    procedure SetEnhReadOnly(AValue: Boolean); virtual;
   protected
    procedure GetReadOnly: Boolean; override;
    procedure SetReadOnly(Value: Boolean); override;
   public
    constructor Create(AOwner: TComponent); override;
  end;   
 
implementation
 
constructor TMyEdit.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEnhReadOnly := inherited ReadOnly;
end;
 
procedure TMyEdit.GetReadOnly: Boolean; override;
begin
  Result := GetEnhReadOnly;
end;
 
procedure TMyEdit.SetReadOnly(Value: Boolean); override;
begin
  SetEnhReadOnly(Value);
end; 
 
function TMyEdit.GetEnhReadOnly(): Boolean;
begin
  Result := FEnhReadOnly;
end;
 
procedure TMyEdit.SetEnhReadOnly(AValue: Boolean);
begin
  if (FEnhReadOnly <> AValue) then
   begin
    FEnhReadOnly := AValue;
   end;
end;   
 
Die Property selbst müsstest du nur überschreiben, wenn die originale property keine oder statische Methoden verwedent. Dann sollte folgender Code funktionieren (oder es ist ein Bug).

Code: Alles auswählen

var lBoolean: Boolean; MyEdit1: TMyEdit;
lBoolean := MyEdit1.ReadOnly;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TypeCast - Problem

Beitrag von TBug »

Sorry!!!

Liest denn wirklich keiner die eigentliche Frage?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TypeCast - Problem

Beitrag von mse »

TBug hat geschrieben: Es geht bei der Frage nicht darum, wie man eine Property setzen kann, sondern warum der TypeCast nicht wie gewünscht/erwartet funktioniert und ob Lazarus hierfür eine Lösung (Compilerschalter?) bietet oder ob es einfach nur ein Bug ist.
"as" ist etwa

Code: Alles auswählen

 
if not (MyEdit1 is TEdit) then begin
 raise exception.create(...
end;
...
 
http://www.freepascal.org/docs-html/ref ... 100012.8.7
Was hast du denn erwartet?

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TypeCast - Problem

Beitrag von TBug »

mse hat geschrieben:Was hast du denn erwartet?
Das es so funktioniert, wie unter Delphi.

Also, dass bei einem SoftCast mit "as" die Properties der Komponente genommen werden und nicht die des Vorgängers!


.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TypeCast - Problem

Beitrag von mse »

???
Das macht es doch? Du verlangst "as TEdit" darum bekommst du auch "TEdit". Was verstehst du denn unter "soft cast"?

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TypeCast - Problem

Beitrag von TBug »

mse hat geschrieben: Was verstehst du denn unter "soft cast"?
Soft-TypeCast : (MyEdit1 as TEdit).ReadOnly
Hard-TypeCast : TEdit(MyEdit1).ReadOnly
mse hat geschrieben: Das macht es doch?
Eben nicht.

Code: Alles auswählen

 
MyEdit1 := TMyEdit.Create();
MyEdit1.ReadOnly := true;
 
Lazarus:

Code: Alles auswählen

 
lBoolean := MyEdit1.ReadOnly                //Result: true
lBoolean := TEdit(MyEdit1).ReadOnly      //Result: false
lBoolean := (MyEdit1 as TEdit).ReadOnly //Result: false
 
Delphi:

Code: Alles auswählen

 
lBoolean := MyEdit1.ReadOnly                 //Result: true
lBoolean := TEdit(MyEdit1).ReadOnly      //Result: false
lBoolean := (MyEdit1 as TEdit).ReadOnly //Result: true
 

.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: TypeCast - Problem

Beitrag von Socke »

Um auf deine ursprüngliche Frage zurückzukehren:
TBug hat geschrieben:Bug oder Feature ???
Bug. Ab zum Kammerjäger.

Da Free Pascal mit Delphi kompatibel sein möchte, kannst du solche Unterschiede direkt im Bug-Tracker suchen bzw. eintragen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: TypeCast - Problem

Beitrag von wp_xyz »

Nein. Welche Delphi-Version hast du denn? Bei XE2 ergeben beide Programme, die du im Bug-Report angehängt hast, dasselbe Ergebnis - siehe Screenshots. Ich habe noch Delphi 7, da finde ich das von dir geschilderte Verhalten.

Und das ist auch richtig so, weil - wie oben mse festgestellt hat - die Getter/Setter für ReadOnly virtuell sind. Das heißt, es werden immer die Setter/Getter der Klasse aufgerufen, die die Instanz erzeugt hat, also MyEdit, egal wie du die Typen wandelst.

Von wegen "Unzulänglichkeiten von Lazarus"...
Dateianhänge
ReadOnly-Laz.png
ReadOnly-XE2.png

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TypeCast - Problem

Beitrag von TBug »

wp_xyz hat geschrieben:Welche Delphi-Version hast du denn?
Delphi2007
TypeCast.jpeg

baumina
Beiträge: 152
Registriert: Mo 3. Feb 2014, 14:07
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: TypeCast - Problem

Beitrag von baumina »

Also XE zeigt auch noch das beschriebene Verhalten, was neueres hab ich leider nicht.
.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: TypeCast - Problem

Beitrag von mse »

TBug hat geschrieben:
mse hat geschrieben: Was verstehst du denn unter "soft cast"?
Soft-TypeCast : (MyEdit1 as TEdit).ReadOnly
Hard-TypeCast : TEdit(MyEdit1).ReadOnly
Da ist kein Unterschied. "(MyEdit1 as TEdit).ReadOnly" und "TEdit(MyEdit1).ReadOnly" sind dasselbe, bei "as" wird lediglich geprüft, ob die Instanz tatsächlich ein "TEdit" ist, siehe den Link zur Free Pascal Dokumentation. Auch bei Delphi ist das so dokumentiert:
http://docwiki.embarcadero.com/RADStudi ... s_Operator
Irgend etwas stimmt da nicht...

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: TypeCast - Problem

Beitrag von wp_xyz »

Ein wesentlicher Unterschied besteht zwischen XE2 und Lazarus: bei XE2 sind die Getter/Setter nicht virtuell, bei Lazarus dagegeben schon. Bei XE2 sind sie aber anders implementiert als bei Delphi 7, ob dieser Unterschied ausreicht, das geänderte Verhalten zwischen den beiden Delphis zu erklären, oder ob Emba da einen Bug eingebaut hat, kann ich nicht sagen, und werde es auch nicht näher untersuchen.

Antworten