Autor |
Beitrag |
harryp
Beiträge: 52
Erhaltene Danke: 9
Win 8.1
Delphi 7, XE8
|
Verfasst: Sa 28.01.17 19:58
Liebe EE-Experten,
einer meiner Schüler hat mich in der gerade endenden Woche überrascht. Ich war bisher fest davon überzeugt, dass Variablen und Variablentypen in Delphi unterschiedliche Bezeichner benötigen. Wenn ich das beim Deklarieren von Variablen teste (z.B. einen Typen a = String[10]; festlege und var a:a; teste), bekomme ich auch die erwartete Fehlermeldung.
Nun hat der Schüler sein Memofeld netterweise TMemo genannt. Hier entsteht keine Fehlermeldung, etwa beim Aufruf von TMemo.Lines.Add('...'); sondern das Programm läuft problemlos.
Daher meine Fragen:
- Kennt ihr einen erklärbaren Grund, dass Delphi hier scheinbar bei Komponenten eine Ausnahme macht?
- Kann es bei der Gleichbenennung von Objekt und zugehöriger Komponentenklasse zu Problemen im Aufruf kommen (z.B. bei Konstruktormethoden) oder gibt es andere gute Gründe (abgesehen vom Programmierstil) dafür, dass man seine Objekte nicht wie die Komponenten benennt?
Vielen Dank vorab für die Antworten und ein schönes Restwochenende.
|
|
Slipstream
Beiträge: 26
Erhaltene Danke: 5
|
Verfasst: Sa 28.01.17 23:32
Habe das soeben einmal mit D7 getestet:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| unit UnitMain;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TFormMain = class(TForm) TMemo: TMemo; TButton: TButton; procedure TButtonClick(Sender: TObject);
private
public
end;
var FormMain: TFormMain;
implementation {$R *.dfm}
procedure TFormMain.TButtonClick(Sender: TObject); begin TMemo.Lines.Append('Das ist ein Text.'); end;
end. |
Dass das tatsächlich funktioniert, dürfte mit den unterschiedlichen Namensräumen zusammenhängen. Der Typ TMemo oder ein anderer wie TButton ist in der Unit StdCtrls deklariert und stellt eine eigene Klasse dar. Beim Parsen weiss der Delphi-Compiler sofort, dass das TMemo vor dem Doppelpunkt eine Variable sein muss, die nur innerhalb der Forumlarklasse (TFormMain) Gültigkeit besitzt. Vor dem Doppelpunkt stehen nämlich immer Variablen. Beim Parsen des TMemo hinter dem Doppelpunkt weiss der Delphi-Compiler sofort, dass es sich um einen Typ handeln muss, denn hinter dem Doppelpunkt steht immer der Typ. Der Parser findet jedoch keinen solchen Typen in der Formularklasse. Also klappert er die Uses ab und findet dort in der Unit StdCtrls den Typen TMemo. Damit sind die beiden zwar identischen Bezeichner dennoch korrekt unterschiedlichen Ursprüngen zugewiesen.
Probleme kann es eigentlich nicht geben, denn Delphi verhindert das Compilieren von Code, der doppelte Deklarationen enthält. Wenn du also in derselben Klasse oder in derselben Unit zweimal denselben Bezeichner verwenden würdest, würde der Build-Vorgang mit einer entsprechenden Fehlermeldung abbrechen.
Man sollte sich aber dennoch an die Konventionen zur Vergabe von Bezeichnern halten und Typen stets mit einem vorangestellten T markieren. Variablen sollten diese vorangestellte T dagegen nicht aufweisen. Diese Konventionen dienen vor allem der besseren Lesbarkeit von Code, egal in welcher Programmiersprache.
Für diesen Beitrag haben gedankt: harryp
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 29.01.17 00:41
- Nachträglich durch die Entwickler-Ecke gelöscht -
Für diesen Beitrag haben gedankt: harryp
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 29.01.17 02:06
Slipstream hat folgendes geschrieben : | Beim Parsen weiss der Delphi-Compiler sofort, dass das TMemo vor dem Doppelpunkt eine Variable sein muss, die nur innerhalb der Forumlarklasse (TFormMain) Gültigkeit besitzt. Vor dem Doppelpunkt stehen nämlich immer Variablen. Beim Parsen des TMemo hinter dem Doppelpunkt weiss der Delphi-Compiler sofort, dass es sich um einen Typ handeln muss, denn hinter dem Doppelpunkt steht immer der Typ. |
So schlau ist der Compiler nicht. Bezeichner müssen eindeutig sein.
Das lässt sich auch leicht zeigen. Das funktioniert auch nicht: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure Test; const TMemo = False; var TestVariable: TMemo; begin
end; | Delphi findet unter dem Namen TMemo die Konstante und wirft einen Fehler.
Das Entscheidende ist der Scope. Es wird immer der Bezeichner genommen, der "am nächsten dran" deklariert ist.
Übrigens kompiliert auch das:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure Test; const True = False; begin if True then ShowMessage('Ja') else ShowMessage('Nein'); end; | Und es wird auch wirklich Nein angezeigt.
Für diesen Beitrag haben gedankt: harryp
|
|
Slipstream
Beiträge: 26
Erhaltene Danke: 5
|
Verfasst: So 29.01.17 02:51
Für diesen Beitrag haben gedankt: harryp
|
|
mandras
Beiträge: 430
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: Mi 01.02.17 21:05
Du kannst auch sagen
var
integer : byte;
boolean : char;
weiter unten geht dann auch:
boolean := '4';
Es liegt einfach daran daß links ein Variablenname erwartet wird, rechts ein Typ.
Durch Definition einer Variable mit Namen "integer" wird der Typ Integer auch nicht gelöscht, überschrieben oder ähnliches.
Was nicht geht:
var
string : integer;
Da schreit Delphi, das liegt aber daran, daß "string" im Ggs zum Rest ein reserviertes Wort ist (wird vom Syntaxhighlighter auch immer fett angezeigt)
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 03.02.17 04:39
mandras hat folgendes geschrieben : |
Durch Definition einer Variable mit Namen "integer" wird der Typ Integer auch nicht gelöscht, überschrieben oder ähnliches.
|
Trotzdem ist er aber im Scope der Variablen nicht mehr als Typ nutzbar. Genau das habe ich ja mit dem Quelltext oben gezeigt.
|
|
|