Typenumwandlung und as ?

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Typenumwandlung und as ?

Beitrag von Mathias »

Ich habe da 2 verschiedene Varianten um einen Button auszuwerten. funktionieren tun beide.
Welches ist der Vor- und Nachteil der beiden Varianten ?
Wobei mir ersteres sympatischer erscheint.

Code: Alles auswählen

procedure TForm1.ButtonClick(Sender: TObject);
begin
  if TButton(Sender) = Button2 then begin
    ShowMessage('Button2 gedrückt');
  end;
  if (Sender as TButton) = Button3 then begin
    ShowMessage('Button3 gedrückt');
  end;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: Typenumwandlung und as ?

Beitrag von wp_xyz »

Um zu prüfen, ob Sender gleich Button2 ist, dafür brauchst du gar keine Typumwandlung, denn sowohl Sender als auch Button2 sind Abkömmlinge von TObject, so dass man die Pointer auf Gleichheit prüfen kann.

Code: Alles auswählen

if Sender = Button2 then ShowMessage('Button2 gedrückt');

Wenn du wissen willst, ob Sender allgemein ein TButton ist oder ein Nachfahre davon (also nicht die Instanz Button2), nimmt man den Operator "is":

Code: Alles auswählen

if (Sender is TButton) then ShowMessage('Es wurde irgendein Button gedrückt.');

"as" prüft dasselbe wie "is", und erzeugt eine Exception "invalid type cast", falls Sender keine Instanz von TButton oder einem Nachfahren ist. Andernfalls wird eine Typumwandlung nach TButton ausgeführt.

Die ungeprüfte, einfache Typumwandlung TButton(Sender) fliegt dir irgendwann unkontrolliert um die Ohren, wenn Sender kein TButton ist, vor allem, wenn schreibend auf die Properties des Nicht-Buttons zugegriffem wird oder dessen Methoden aufgerufen werden.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Typenumwandlung und as ?

Beitrag von Mathias »

Code: Alles auswählen

if Sender = Button2 then ShowMessage('Button2 gedrückt');
Das dies so einfach geht, man lernt immer wieder dazu. :shock:

Nur schade, das so etwas nicht geht:

Code: Alles auswählen

  case Sender of
    MenuItemPlus: begin
      if CubeSize < 7 then begin
        Inc(CubeSize);
      end;
    end;
    MenuItemMinus: begin
      if CubeSize > 0 then begin
        Dec(CubeSize);
      end;
    end;
  end;


Dies wäre einige eleganter als die if else Verschachtelung.

Code: Alles auswählen

  if Sender = MenuItemPlus then begin
    if CubeSize < 7 then begin
      Inc(CubeSize);
    end;
  end else if Sender = MenuItemMinus then begin
    if CubeSize > 0 then begin
      Dec(CubeSize);
    end;
  end;


Für das is habe ich auch noch eine Verwendung gefunden.

Code: Alles auswählen

  if (Sender is TButton) then begin
    Label1.Caption := TButton(Sender).Caption;
  end;   
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Typenumwandlung und as ?

Beitrag von theo »

Mathias hat geschrieben:Nur schade, das so etwas nicht geht:


Dafür gibt es genügend Alternativen. Z.B. über den Tag, oder auch so:

Code: Alles auswählen

  case (Sender as TComponent).Name of
     'Button1': begin
       Caption:='b1';
     end;
     'Button2': begin
       Caption:='b2';
     end;
   end;   

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Typenumwandlung und as ?

Beitrag von Mathias »

Wer garantiert dir, das der .Name gleich ist, wie der Variablenname ?
Besonders, wen der Button dynamisch erzeugt wurde.
Diese Procedure spuckt einen Leerstring aus.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var
  button: TButton;
begin
  button := TButton.Create(Self);
  button.Parent := Self;
  ShowMessage(button.Name);
end;

Und Tag mit irgendwelchen Nummern ist recht fehleranfällig.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Typenumwandlung und as ?

Beitrag von kupferstecher »

Mathias hat geschrieben:Nur schade, das so etwas nicht geht:

Ich bevorzuge zwar sowieso if...elsen, aber wuerde es so nicht gehen?

Code: Alles auswählen

  case ptruint(Sender) of
    ptruint(MenuItemPlus): begin
    ...

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Typenumwandlung und as ?

Beitrag von theo »

Mathias hat geschrieben:Wer garantiert dir, das der .Name gleich ist, wie der Variablenname ?

Der Programmierer? Spielt doch keine Rolle.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Typenumwandlung und as ?

Beitrag von theo »

kupferstecher hat geschrieben:
Mathias hat geschrieben:Nur schade, das so etwas nicht geht:

Ich bevorzuge zwar sowieso if...elsen, aber wuerde es so nicht gehen?

Code: Alles auswählen

  case ptruint(Sender) of
    ptruint(MenuItemPlus): begin
    ...


Nein, unten muss es eine Konstante sein.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Typenumwandlung und as ?

Beitrag von Mathias »

Irgendwie komisch, das case mit Strings funktioniert, aber nicht mit Classen, obwohl dies nur Pointer(Integer) sind.
Dies wäre sicher eine gute Features-Erweiterung.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Typenumwandlung und as ?

Beitrag von theo »

Wie gesagt, der Vergleich (nach dem of) muss eine Konstante sein.

'Button1' ist eine Stringkonstante, Button1 ist aber keine Konstante. Du weißt ja nicht vor dem Kompilieren und Ausführen, welche Speicheradresse Button1 bekommt, sonst könnte man da theoretisch auch eine Zahl angeben.

Die sauberste Variante ist wahrscheinlich die mit dem Tag.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Typenumwandlung und as ?

Beitrag von Mathias »

Wie gesagt, der Vergleich (nach dem of) muss eine Konstante sein.

Das habe ich übersehen, jetzt ist der Fall klar. :oops:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: Typenumwandlung und as ?

Beitrag von wp_xyz »

Code: Alles auswählen

  if (Sender = MenuItemPlus) and (CubeSize < 7) then 
    Inc(CubeSize)
  else if (Sender = MenuItemMinus) and (CubeSize > 0) then
    Dec(CubeSize);

... wäre dich auch ganz schön kompakt

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Typenumwandlung und as ?

Beitrag von Mathias »

Das CubeSize ist nur ein Beispiel.
Was störend wirkt, wen man mehrer Menupunkte abfragen muss und dabei muss der Bezeichner Sender zig mal stehen.
Ein Case of würde sowas viel übersichtlicher machen. Ich denke, es wäre sicher möglich FPC zu modifizieren, das sowas auch geht.
Ein normales case of arbeitet intern auch mit (if then else ) oder mit jmp, jp, etc.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten