| Autor |
Beitrag |
flowstar
      
Beiträge: 123
WinME
D6 Enterprise
|
Verfasst: Fr 19.03.04 18:08
Ich hab mal ne Frage zur Delphi Syntax:
Warum heisst es bei der Erstellung von Instanzen
Delphi-Quelltext 1:
| Test := TKlasse.Create |
und nicht
Delphi-Quelltext
Hat das nen sinn?
Zuletzt bearbeitet von flowstar am Fr 19.03.04 18:23, insgesamt 1-mal bearbeitet
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Fr 19.03.04 18:09
Hallo!
Bitte ändere den Titel des Topics da er wenig über das eigentlich Thema verrät. Hier der entsprechende Absatz aus den Delphi-Forum.de Richtlinien:
| Richtlinien hat folgendes geschrieben: |
1.1 Beiträge
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist.[...]
|
Einfach oben bei deinem ersten Beitrag auf "Edit" klicken und den Titel ändern. Dank Dir!
Gruß Peter Lustig
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: Fr 19.03.04 18:12
Erstens mal ists keine blöde Frage sondern ein blöder Titel - bei sowas wundere dich nicht, wenn du in Zukunft keine Ahnung kriegst. Stehst sich schon auf der watchlist von einigen.
Zweitens ist Create ein constructor - der reserviert Speicher und gibt eine Referenz auf diese Objekt-Instanz zurück.
Wenn du xxx.Create schreibst, dann verwendest du bereits eine Instanz - die gibts aber noch nicht, weil Delphi keine statische Erzeugung von Objekten unterstützt. Somit hats du zu beginn nur eine ungültige Referenz-Variable, welcher du mit Create eine gültige zuweist.
//Edit: Die Mods sind aber heute wieder flott. 
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
flowstar 
      
Beiträge: 123
WinME
D6 Enterprise
|
Verfasst: Fr 19.03.04 18:23
Besser so?
Ihr seid heute aber mal wieder gut gelaunt...
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: Fr 19.03.04 18:31
::flowstar
Joo - das bin ich  - weil in spätestens 3 Stunden und 30 Minuten bin ich dort: www.cosmiceye.org/party.htm - weil dort werden morgen sein, die da: www.astral-projection.com .
Womit eindeutig Schlußzufolgern ist: Es wird eine Menge netter, fescher, halbnackter Mädls dort auch sein - daher kann ich nur gut drauf sein  .
Und weil ich beweisen will, daß ich sogar noch besser drauf sein kann als andere:
Hier der Beweis, daß wir gar nicht so übel sind: www.lugbz.org/docume...rt-questions_de.html
Frage übrigends beantwortet ?
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Fr 19.03.04 18:36
Eigentlich ist es unlogisch. Denn, einerseits scheibe ich
Delphi-Quelltext 1: 2:
| var Bitmap: TBitmap; |
und dann muß ich noch mal
Delphi-Quelltext 1:
| Bitmap := TBitmap.Create; |
schreiben.
Was erwartet der Compiler wenn ich eine Bitmap Variable vom Typ TBitmap deklariere? Erwartet der, daß ich später ein Icon Objekt erstelle? Eigentlich ist es doppelte Pflege. Entweder einfach nur einen Zeiger deklarieren und erst später den Typ bei Create festlegen, oder beim deklarieren den Typ zuweisen und später einfach nur noch Create. Eine ander Möglichkeit hat man sowieso nicht, oder?
Oder kann einer genau sagen wieso es wichtig ist zwei mal drauf hinzuweisen was für Typ es ist?
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Fr 19.03.04 18:38
| Zitat: | | //Edit: Die Mods sind aber heute wieder flott. |
Möchtest Du damit dezent anmerken, dass wir manchmal nicht flott sind?
//edit:
Du kannst Deine Variable ja auch als Referenz auf ein bereits erzeugtes Objekt benutzen und musst dann gar kein neues Objekt erzeugen
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Zuletzt bearbeitet von Christian S. am Fr 19.03.04 18:40, insgesamt 1-mal bearbeitet
|
|
MaxiTB
      
Beiträge: 679
Win2000, WinXp, Workbench ;-)
D7 Ent, VS2003 Arch.
|
Verfasst: Fr 19.03.04 18:40
::bms
Du mußt den constructor sehen wie eine statische Methode - ähm - tschuldigung, Klassenmehtode heißts auf Delphisch.
Das heißt, bei Klassenmethoden gibts du ja auch die Klasse an Punkt Methode.
Mit der Variablendeklaration erzeugst du ja nur eine Referenz auf ein Objekt - und die weißt du später zu.
::peter
Hätte ich schreiben sollen zuuu flott ? *g*
Ich denke mal, daß besprechen wir mal lieber bei einem Bier ... ähm - aber dann bitte keine C/Delphi Performance Diskusssion - davon hatte ich heute schon genug  .
_________________ Euer Mäxchen
Wer früher stirbt, ist länger tot.
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 19.03.04 19:47
| bms hat folgendes geschrieben: | | Was erwartet der Compiler wenn ich eine Bitmap Variable vom Typ TBitmap deklariere? Erwartet der, daß ich später ein Icon Objekt erstelle? |
Du übersiehst, dass jedes Objekt, das du erstellst, nicht nur einfach angelegter Speicher ist. Mit jedem Objekt verbunden sind Methoden, die vielleicht nur unter ganz bestimmten Bedingungen ausgeführt werden können.
Angefangen schon beim Konstruktor: Vielleicht braucht der eine bestimmte Variable oder ein anderes Objekt, wie einen Parent. Oder eine Prozedur muss vorher eine benötigte dll-Datei laden.
Da Delphi natürlich nicht wissen kann, wann es sicher ist, die Komponente zu erstellen, musst du es selber in deinem Code machen.
Da es in Delphi jedoch üblich ist, alle Variablen und Objekte, die du im Code nennen willst, vorher zu deklarieren, musst du vorher schon die Variable anlegen, in die dein Konstruktor dann die Komponente erstellen kann.
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Fr 19.03.04 19:50
| MaxiTB hat folgendes geschrieben: | Du mußt den constructor sehen wie eine statische Methode - ähm - tschuldigung, Klassenmehtode heißts auf Delphisch.
Das heißt, bei Klassenmethoden gibts du ja auch die Klasse an Punkt Methode.
Mit der Variablendeklaration erzeugst du ja nur eine Referenz auf ein Objekt - und die weißt du später zu. |
Das Prinzip ist mir klar, nur erscheint es mir nicht logisch, daß es zwei mal sein muß. Allerdings kann ich mich damit abfinden, daß es bei Pascal so sein muß da es nicht anders ging (gemeint sind die Pascalkonventionen). Wenn ich zum Beispiel den Code-Vervollständiger nutze und hinter einer Bitmapvariable, d.h. hinter "Bitmap :=", STRG + LEERTASTE drücke, dann wird der korrekte Klassentyp angeboten (vorausgesetzt ich hab Bitmap als TBitamp deklariert). Delphi weiß also was kommen muß, verlangt aber dennoch das man TBitamp noch mal vor Create plaziert. Ich kann mir vorstellen, daß es auch anders und einfacher funktionieren könnte. Aber ich hab keine Probleme damit. Wenn aber eines sagen könnte wieso es so sein muß, dann wäere es nicht schlecht.
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 19.03.04 19:59
Hallo???
Hast du meinen Post gelesen?
Na ja... schätze war gleichzeitig.
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Fr 19.03.04 21:08
Eigentlich ist es egal und nicht so wichtig. Ich hab das Prinzip schon verstanden.
Es geht nicht drum, daß es gemacht wird. Die Frage ist also nicht warum man an erst an einer Stelle mit Create ein Objekt erstellt. Das sind nicht die Fragen. Die Frage ist wieso nicht einfach ein Create. Wieso haben die Entwickler von Delphi es so vorgesehen und nicht anders. Wieso nicht einfach ein
Delphi-Quelltext 1: 2: 3: 4:
| var Bitmap: TBitmap; begin Bitmap.Create; |
oder mindesten
Delphi-Quelltext 1:
| Bitmap := Object.Create; |
Was kann es anderes sein als TBitmap. Eigentlich dürfte es kein Problem sein. Der Compiler weiß, daß es NUR TBitmap sein kann, da Bitmap vom Typ TBitmap ist.
Wenn ich es so mache.
Delphi-Quelltext 1: 2: 3: 4:
| var Bitmap: TBitmap; begin Bitmap := TBitmap.Create; |
dann schreibe ich zwei mal TBitmap, also ein mal doppelpflege.
Aber ich gehe davon aus, daß Delphi (oder genauer Pascal) nicht als Objektsprache entwickelt wurde. Deshalb hat man sich etwas zusammengeschustert was man noch als Pascal verkaufen konnte.
|
|
UC-Chewie
      
Beiträge: 531
WinXP
D5 Ent
|
Verfasst: Fr 19.03.04 21:19
| bms hat folgendes geschrieben: | | Was kann es anderes sein als TBitmap. Eigentlich dürfte es kein Problem sein. Der Compiler weiß, daß es NUR TBitmap sein kann, da Bitmap vom Typ TBitmap ist. |
Und genau da liegt dein Irrtum. Du kannst durchaus in dem von dir genannten Fall eine Instanz vom einer von TBitmap abgeleiteten Klasse erstellen. Das Stichwort dazu lautet POLYMORPHIE bzw. POLYMORPHISMUS, zu deutsch "Vielgestaltigkeit".
_________________ Egal wie dumm man selbst ist, es gibt immer andere, die noch dümmer sind
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 19.03.04 21:29
Du kannst aber TBitmap.Create auch aufrufen, ohne das Ergebnis in eine Variable zu schreiben (das ginge sonst nicht).
Sinnvoll z.B. für Klassen, die sich sebst irgendwo registrieren.
Auch hat man so die Möglichkeit, für eine bestehende Instanz noch einmal Create ausführen zu lassen, ohne eine neue Instanz zu erstellen.
Nebenbei finde ich die Syntak eigentlich so ganz logisch und verstehe überhaupt nicht, weshalb du dich so aufregst...
Man ruft ja eine Funktion auf, nämlich den Konstruktor, und weist der Variablen auf der linken Seite deren Ergebnis zu (die neu geschaffene Instanz).
Vielleicht steht links bis jetzt nil, oder eine alte Referenz auf ein längst freigegebenes Objekt. Aber auf jeden fall steht da nichts nichts, mit dem ich etwas ausführen möchte, sondern etwas, von dem ich möchte, dass es überschrieben wird.
Für mich total logisch!!
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Fr 19.03.04 22:23
Ok, lassen wir es. Anscheinend wird die Frage immer wieder mißverstanden. Ist auch nicht schlimm. Nur geht es mir die ganze Zeit um was anderes. Aber irgendwie kann ich nicht verständlich machen was ich meine. Ist egal.
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 20.03.04 08:38
Was denn?
Du hast gefragt, warum man erst bei der Deklaration " : TBitmap" schreibt und dann beim Aufruf des Konstruktors nochmal " := TBitmap.Create ".
Genau das haben dir jetzt einige Leute beantwortet. Was daran jetzt noch falschverstanden werden könnte, ist mir nicht klar.
Ich stimme jetzt vielleicht so weit überein, dass man den Compiler auch hätte veranlassen können bei...
Delphi-Quelltext 1: 2: 3:
| Var Test:TBitmap; ... Test:=Create; |
...automatisch ein TBitmap zu erstellen. Trotzdem müsste dann aus genannten Gründen aber wenigstens die Möglichkeit bleiben, ein anderes Create aufzurufen.
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Sa 20.03.04 09:28
Siehst du, über mehr wollte ich auch nicht diskutieren. Mir ist bewußt, daß es mehrere Konstruktoren geben kann und das einige Klassen auch mehrere Konstruktoren haben. Mir ist bewußt, daß es Polymorphie gibt und wozu sie dient. Mir ist auch bewußt, daß ich ein Objekt erstellen kann ohne eine Variable. Mir ist auch der Unterschied zwischen einer Variable, einer Klasse und einem Objekt bewußt. All das weiß ich und über das wollte ich auch nicht reden. Aber ich weiß von vielen Anfängern, durch vierschiedenen Forumsfragen, was viele gerade am Anfang für verwirend halten. Warum gerade so und nicht anders. Würde ich eine Objektorientierte Programmiersprache entwickeln, dann hätte ich einige anders gemacht. Ich hab mir mal Gedanken gemacht über Delphi und wie Delphi mit Objekten umgeht. Und meiner Meinung nach ist das nicht optimal. Es sieht irgendwie zusammengeschustert aus. Daruber wollte ich diskutieren, nur darüber.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Sa 20.03.04 14:05
Es gibt einen Unterschied zwischen zwischen den beiden Aufrufen.
Delphi-Quelltext 1: 2: 3: 4: 5:
| var aBitmap: TBitmap;
aBitmap := TBitmap.Create; aBitmap.Create; |
Im ersten Fall wird Create als Constructor aufgerufen, also quasi als Klassenmethode die ohne ein Objekt auskommt. Stattdessen wird eben ein neues Objekt der angegebenen Klasse erzeugt und die Referenz darauf zurückgegeben.
Im zweiten Fall wird Create als Methode aufgerufen, und zwar nicht mehr als Klassenmethode, sondern als Methode das Objekts (in diesem Fall eben aBitmap). Es wird kein neues Objekt erzeugt, sondern es wird nur ganz normal der Code der Create-Methode abgearbeitet und in diesen Fall eben auf das Objekt bezogen über das die Methode aufgerufen wurde.
Das ist auch wichtig, dass es diese Unterscheidung gibt! Wenn du dich ein bisschen in OOP auskennst weißt du zB, dass man einen Konstruktor überschreiben kann und über inherited den geerbten Konstruktor aufrufen kann. zB:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| type TMyFirstClass = class(TObject): private F: Integer; public constructor Create(x: Integer); virtual; end;
TMySecondClass = class(TMyFirstClass ) public constructor Create(x: Integer); override; end;
constructor TMyFirstClass.Create(x: Integer); begin inherited Create; F := x; end;
constructor TMySecondClass.Create(x: Integer); begin inherited Create(x); F := F + x; end; |
Stell dir nun vor es wird mit folgendem Code eine Instanz von TMySecondClass erstellt:
Delphi-Quelltext 1: 2: 3: 4:
| var aObject: TMySecondClass;
aObject := TMySecconfClass.Create(5); |
Was passiert da nun wirklich? Zuerst wird der Konstruktor von TMySecondClass aufgerufen und zwar als Konstruktor und nicht als Methode, es wird also eine Instanz von TMySecondClass erstellt und dann der Code des Konstruktors aufgerufen. Aber was passiert da in dieser Zeile?
Delphi-Quelltext
Hier wird der geerbte Konstruktor von TMyFirstClass aufgerufen, aber eben nicht als Konstruktor der ein neues Objekt erzeugt, sondern im Prinzip als normale Methode die sich auf das Objekt bezieht das der Konstruktor von TMySecondClass erstellt hat. Das muss ja auch so sein, da der geerbte Konstruktor dafür verantwortlich ist die geerbten Eigenschaften und Felder mit brauchbaren Werten zu füllen!
Ich hoffe das hilft dir ein bisschen das ganze zu verstehen, auch wenn das Beispiel vielleicht nicht ganz so gut zeigt was ich dir zu erklären versuche. Noch deutlicher wird das ganze wenn du mehrere verschiedene Klassen hast und jede mit mehreren verschiedenen Konstruktoren die sich untereinander selbst aufrufen und zwar sowohl von der eigenen Klasse als auch von den Basisklassen (wie ich es gerade in einem meiner Projekte habe). Aber so ein Beispiel hier anzuführen sprengt etwas den Rahmen und wäre auch zu kompliziert zum erklären...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 20.03.04 15:39
Hm... das hatten ja schon mehrere oben erklärt, wenn auch keiner so ausführlich.
Also wenn ich flowstar jetzt richtig verstanden habe, dann ging es ihm auch gar nicht darum.
Er wollte nur wissen, warum es keine Kompilervereinfachung gibt, die es einem erspart, zwei mal TBitmap schreiben zu müssen.
Jetzt wo's hier aber alles schon mal so ausführlich steht, sollte man es vielleicht als gekürzte Fassung in die FAQ übernehmen.
Am besten gleich dazu beantworten, warum man mit TBitmap:=TBitmap keine Instanzen kopiert und warum und wann man Free aufrufen sollte.
|
|