| Autor |
Beitrag |
FD-83
      
Beiträge: 49
|
Verfasst: So 27.02.05 17:11
Wo genau liegt eigentlich der Unterschied zwischen den beiden TypeCast Varianten?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Button1Click(Sender: TObject); begin (Sender as TButton).Caption := 'klick'; end;
procedure TForm1.Button1Click(Sender: TObject); begin TButton(Sender).Caption := 'klack'; end; |
Funktionieren tut ja beides. Sind das 2 Schreibweisen für die gleiche Sache oder gibts wirklich einen Unterschied?
Gruss Frederik
|
|
Larus
      
Beiträge: 431
|
Verfasst: So 27.02.05 17:37
|
|
FD-83 
      
Beiträge: 49
|
Verfasst: So 27.02.05 17:59
Das nennt man Casting. Damit kann man Objekte von einem Klassen- oder interfaceTyp in einen anderen Umwandeln. Vorrausgesetzt sie sind in der selben Vererbungshirachie bzw. implementieren das entsprechende Interface.
Im Beispiel oben hast du den Sender des Ereignisses (also den Button) nur als TObject vorliegen. Ein TObject hat aber keine Eigenschaft Caption. Daher muss man die TObject Variable erst in eine vom Typ TButton casten. Das funktioniert, weil ein TButton (so wie alle anderen Klassen) vom Typ TObject abstammen.
So ganz grob. Richtig verstehen kann man das nur, wenn man sich etwas mehr mit OOP beschäftigt...
Gruß
Frederik
|
|
Larus
      
Beiträge: 431
|
Verfasst: So 27.02.05 18:13
achso also mit anderen Worten.... Nur der Button der gerade auf diese Funktion zugreift wird umbenannt? (Wie im Beispiel)
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 27.02.05 18:29
| Larus hat folgendes geschrieben: | | achso also mit anderen Worten.... Nur der Button der gerade auf diese Funktion zugreift wird umbenannt? (Wie im Beispiel) |
Mit anderen Worten? Die Aussage ist oben nirgends enthalten. Es wird auch nichts umbenannt sondern der Typ wird gecastet.
TButton(Sender) ist ähnlich wie wenn man Byte('A') schreibt, um raus zu finden welche Nummer in der Ascii-Tabelle das Zeichen 'A' hat. TButton(Sender) heisst einfach, was immer bei der Speicheradresse für Sender ist, soll jetzt ein TButton sein.
Ich denk in Delphi 1 kannst du sogar String(F) schreiben (meinetwegen "String((@F)^)" in späteren Versionen), wobei F ein real ist. Da bekommst du dann ziemlichen Müll raus. Da musst du aufpassen.
"Sender as TButton" liefert eine Referenz auf "Sender" mit dem Typ TButton. Kann "Sender" gar kein TButton sein, dann gibt es eine Exception. "Sender as TButton" erzeugt mehr Code als "TButton(Sender)". Das "as" geht natürlich nur mit Klassen.
Zuletzt bearbeitet von delfiphan am So 27.02.05 18:39, insgesamt 1-mal bearbeitet
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: So 27.02.05 18:32
| Larus hat folgendes geschrieben: | | achso also mit anderen Worten.... Nur der Button der gerade auf diese Funktion zugreift wird umbenannt? (Wie im Beispiel) |
Es wird die Beschriftung des Buttons geändert, der gedrückt wurde und deshalb als Sender übergeben wurde.
Der Unterschied liegt daran, dass (Sender as TPanel).Xy eine Fehlermeldung ausgibt, wenn Sender nicht vom Typ Panel ist. Der andere Typcast ignoriert das Stillschweigend und das Programm läuft weiter, sofern das Object die Eigenschaft trotzdem besitzt. Sie wird aber nicht geändert.
Gruß Hape!
//Edit: delfiphans Erklärung ist wohl besser  !
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
Zuletzt bearbeitet von wulfskin am So 27.02.05 18:35, insgesamt 1-mal bearbeitet
|
|
Larus
      
Beiträge: 431
|
Verfasst: So 27.02.05 18:35
gut zu wissen  vieleicht kann man es irgentwanneinmal brauchen.  außerdem is man ja ständig am weiterlesen und lernen 
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 27.02.05 18:42
Übrigens, mit "if Sender is TButton" kannst du überprüfen, ob Sender ein TButton ist...
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 27.02.05 18:46
| wulfskin hat folgendes geschrieben: | | Der andere Typcast ignoriert das Stillschweigend und das Programm läuft weiter, sofern das Object die Eigenschaft trotzdem besitzt. |
Darauf würde ich nicht wetten. Wenn du Glück hast, funktioniert's (z.B. bei .Caption oder .Text). Wenn du Pech hast, wirds einfach irgendwo in den Speicher geschrieben und du merkst es vielleicht nicht mal....
|
|
FD-83 
      
Beiträge: 49
|
Verfasst: Mo 28.02.05 00:59
Also bei Klassen und Interfaces lieber is und as verwenden um Problemen vorzubeugen. So hab ichs bislang auch immer gemacht.
Gruß
Frederik
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 28.02.05 01:17
Der Operator as prüft intern per is ob das Objekt ein Nachfahre der entsprechenden Klasse ist. Daher sind zB Casts wie
Delphi-Quelltext 1: 2:
| if xyObject is TxyClass then (xyObject as TxyClass)... |
vollkommen unnötig, da die Überprüfung per is doppelt stattfindet. Hat man bereits selbst per is geprüft kann man ohne Probleme gleich direkt casten: TxyClass(xyObject)
interfaces dürfen nur per as gecastet werden, da dort eine Menge Hintergrundarbeit stattfindet (QueryInterface-Aufruf etc), und Delphi bei einem Typecast mittels as diese komplett transparent durchführt.
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
IngoD7
      
Beiträge: 629
D7
|
Verfasst: Mo 28.02.05 09:50
| Motzi hat folgendes geschrieben: | | Der Operator as prüft intern per is ob das Objekt ein Nachfahre der entsprechenden Klasse ist. |
Das liest man immer wieder. Ob es so ist, weiß ich nicht. Jedenfalls ist mir der Nutzen einer möglichen Überprüfung in as schleierhaft, denn sie ist nicht mit der Überprüfung mittels is zu vergleichen.
Man darf nämlich nicht den Umkehrschluss ziehen, dass wenn as verwendet wird, dann keine is-Abfrage mehr nötig ist!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| xyObject := nil; if xyObject is TxyClass then (xyObject as TxyClass).xxx; xyObject := nil; if xyObject is TxyClass then TxyClass(xyObject).xxx; xyObject := nil; (xyObject as TxyClass).xxx; xyObject := nil; TxyClass(xyObject).xxx; |
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 28.02.05 10:41
| IngoD7 hat folgendes geschrieben: | | Das liest man immer wieder. Ob es so ist, weiß ich nicht. |
Es ist so, glaub mir..  Wenn man bei einen Cast mittels as per Debugger in der System.pas mitschaut was da passiert findet man sich in einer Funktion "AsClass" wieder, die sowohl eine Pascal, als auch eine ASM Umsetzung hat. Die Pascal-Variante schaut so aus:
Delphi-Quelltext 1: 2: 3: 4: 5:
| begin Result := Child; if not (Child is Parent) then Error(reInvalidCast); end; |
Was deinen Fall 3 betrifft:
Delphi-Quelltext 1: 2: 3:
| xyObject := nil; (xyObject as TxyClass).xxx; |
Wenn man sich vom Pascal-Code der Funktion AsClass ausgeht hast du recht, dann gibt es eine Exception. Die ASM-Umsetzung geht allerdings ein bisschen anders vor, indem sie als erstes überprüft ob die zu castende Objektreferenz nil ist und liefert in diesem Fall keine Exception.
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
retnyg
      
Beiträge: 2754
SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
|
Verfasst: Mo 28.02.05 11:11
und wie bringt man dem compiler bei dass er die asm-version aussführt ? ein DEFINE irgendwo ?
|
|
IngoD7
      
Beiträge: 629
D7
|
Verfasst: Mo 28.02.05 11:17
| Motzi hat folgendes geschrieben: | Was deinen Fall 3 betrifft:
Delphi-Quelltext 1: 2: 3:
| xyObject := nil; (xyObject as TxyClass).xxx; |
Wenn man sich vom Pascal-Code der Funktion AsClass ausgeht hast du recht, dann gibt es eine Exception. Die ASM-Umsetzung geht allerdings ein bisschen anders vor, indem sie als erstes überprüft ob die zu castende Objektreferenz nil ist und liefert in diesem Fall keine Exception. |
Was soll mir das mit der ASM-Umsetzung nun sagen? Delphi jedenfalls geht dann wohl vom Pascal-Code aus, denn die Exception kommt.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 28.02.05 11:41
Die Pascal und ASM-Umsetzung werden durch Compiler-Schalter getrennt:
Delphi-Quelltext 1: 2: 3: 4: 5:
| {$IFDEF PUREPASCAL} {$ELSE} {$ENDIF} |
Da das Symbol PUREPASCAL aber nicht definiert ist wird die ASM-Umsetzung ausgeführt... (so ist zumindest die Situation in meinem D6 Prof)
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
IngoD7
      
Beiträge: 629
D7
|
Verfasst: Mo 28.02.05 11:52
| Zitat: | | Da das Symbol PUREPASCAL aber nicht definiert ist wird die ASM-Umsetzung ausgeführt... (so ist zumindest die Situation in meinem D6 Prof) |
Nun mal Hand auf's Herz:
Folgendes führt bei dir also nicht zur Exception???
Delphi-Quelltext 1: 2: 3: 4:
| var Komp : TComponent; ... Komp := nil; (Komp as TEdit).Clear; |
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 28.02.05 12:04
Genau so schauts aus..!  Extra getestet und mit dem Debugger Schritt für Schritt durchgegangen um zu sehen was da passiert. Hab mir auch mal meine eigene AsClass-Funktion mit dem PurePascal-Code gemacht und die hat (logischerweise) schon zu einer Exception geführt.
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mo 28.02.05 12:09
Purepascal müsste doch genau dasselbe tun wie die asm Version, einfach nicht mit der gleichen Effizienz. Kann doch nicht sein, dass die sich anders verhalten?!? Ich zitiere aus der Hilfe:
"At runtime, object must be (...), or be nil; otherwise an exception is raised."
Da steht nix davon, dass bei nil auch ne Exception geraised wird...
(Ich glaub es euch natürlich schon, finde es einfach ein wenig merkwürdig)
|
|
IngoD7
      
Beiträge: 629
D7
|
Verfasst: Mo 28.02.05 12:19
| Motzi hat folgendes geschrieben: | Genau so schauts aus..! |
Das'n Ding. Habe D7E. Da wirft er die Exception. Ich weiß aber nicht, welchen Teil er ausführt, da ich mich mit dem Debugger nicht so gut auskenne. Eine "Extra-PurePascal-Definition" kann ich jedenfalls nirgends erkennen.
|
|