Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Eigener Konstruktor (https://www.delphipraxis.net/151940-eigener-konstruktor.html)

FriendOfDelphi 7. Jun 2010 13:41

Delphi-Version: 2005

Eigener Konstruktor
 
Hallo!

Ich eine Frage zur Verwendung eigener Konstruktoren.

Allgemein:
Delphi-Quellcode:
Objektreferenz := Klasse.Create;

Konkret:
Delphi-Quellcode:
MeinAuto := TAuto.Create;

Ich möchte erreichen, dass zu dem Zeitpunkt wenn das Objekt erzeugt wird, einige Datenfelder des Objekts mit vorgegebenen Werten und nicht mit Standardwerten initialisiert werden.
Standardwerte sind:
  • Datenfelder mit einem ganzzahligen Datentyp (z.B. Integer) werden mit 0 initialisiert
  • Datenfelder mit einem String-Typ werden durch eine leere Zeichenkette initialisiert
Wie gesagt, wenn "MeinAuto" erzeugt wird, sollen eigene Werte über einen eigenen Konstruktor in die Datenfelder des Objekts geschrieben werden.

Hier die Unit mit der Beispielklassendefinition:
Delphi-Quellcode:
type
  TAuto = class(TObject)
  private
    FFarbe: string;
    procedure SetFarbe(Farbe: string);
    constructor Create(col: string);
  public
    property Farbe: string read FFarbe write SetFarbe;
end;
Delphi-Quellcode:
constructor TAuto.Create(col: string);
begin
  inherited Create; //hierdurch wird der ursprüngliche Konstruktor aufgerufen
  FFarbe:='rosa';
end;
Und hier das Beispielprogramm in einer anderen Unit:
Delphi-Quellcode:
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create;
  LKW.Farbe:='rot';
Leider funktioniert das so nicht.
Die Farbe wird erst mit der Zeile
Delphi-Quellcode:
LKW.Farbe:='rot';
gesetzt. Die Initialisierung des Feldes "Farbe" im Konstruktur
Delphi-Quellcode:
FFarbe:='rosa';
erfolgt nicht.
Was mache ich falsch?

xZise 7. Jun 2010 13:47

AW: Eigener Konstruktor
 
Moin,
was macht denn TAuto.SetFarbe()? Weil den rufst du ja nur im zweiten Fall auf.

Abgesehen davon ist der Konstruktor privat? Wie soll er also aufgerufen werden? Und nebenbei rufst du den falschen Konstruktor auf, weil deiner will ein Parameter.

MfG
Fabian

freak4fun 7. Jun 2010 13:47

AW: Eigener Konstruktor
 
Delphi-Quellcode:
constructor TAuto.Create(col: string);
begin
  inherited Create; //hierdurch wird der ursprüngliche Konstruktor aufgerufen
  FFarbe := col;
end;
Delphi-Quellcode:
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create( 'rot');
Du benutzt den Constructor ohne Parameter in deinem Beispiel. :)

angos 7. Jun 2010 13:51

AW: Eigener Konstruktor
 
Hi,

so wie es da steht, kann es doch gar nicht funktionieren (es sollte einen Compilerfehler geben)

Option 1:
Du übergibst dem Create die Farbe und setzt dementsprechend.

Delphi-Quellcode:
constructor TAuto.Create(col: string);
begin
  inherited Create;
  FFarbe:=col;
end;


procedure TForm1.btnClick(Sender: TObject);
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create('rot');
end;
Option 2:
Du übergibst keine Farbe und nimmst "rosa"

Delphi-Quellcode:
constructor TAuto.Create;
begin
  inherited Create;
  FFarbe:='rosa';
end;


procedure TForm1.btnClick(Sender: TObject);
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create;
  LKW.Farbe:='rot';
end;
vielleicht in dem Zusammenhang auch für dich interessant sind folgende Stichwörter:
overload
override
reintroduze


Gruß
angos

FriendOfDelphi 7. Jun 2010 14:13

AW: Eigener Konstruktor
 
Zitat:

Zitat von freak4fun (Beitrag 1026352)
Delphi-Quellcode:
constructor TAuto.Create(col: string);
begin
  inherited Create; //hierdurch wird der ursprüngliche Konstruktor aufgerufen
  FFarbe := col;
end;
Delphi-Quellcode:
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create( 'rot');
Du benutzt den Constructor ohne Parameter in deinem Beispiel. :)

Du hast natürlich recht.
Da hat sich ein "copy and paste"-Fehler eingeschlichen.
Ich habe da ein weng experimentiert (mit und ohne Parameter).
Wenn die Methode mit Parameter deklariert und implementiert wurde, muss sie natürlich auch mit Parameter aufgerufen werden.
Das soll aber nicht so sein. Bei der Erzeugung des Objekts, soll diesem sofort und ohne weiteres Zutun, die Farbe "rosa" zugewiesen werden.

So sollte es aussehen:
Delphi-Quellcode:
constructor TAuto.Create;
begin
  inherited Create; //hierdurch wird der ursprüngliche Konstruktor aufgerufen
  FFarbe:='rosa';
end;
Delphi-Quellcode:
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create;
Funktioniert aber nicht.

mkinzler 7. Jun 2010 14:15

AW: Eigener Konstruktor
 
Funktioniert schon, könnte oder hat mit großer Wahrscheinlichkeit Seiteneffekte und führt nicht zum gewünschten Ergebnis

FriendOfDelphi 7. Jun 2010 14:18

AW: Eigener Konstruktor
 
Zitat:

Zitat von angos (Beitrag 1026353)
Hi,

so wie es da steht, kann es doch gar nicht funktionieren (es sollte einen Compilerfehler geben)

Option 1:
Du übergibst dem Create die Farbe und setzt dementsprechend.

Delphi-Quellcode:
constructor TAuto.Create(col: string);
begin
  inherited Create;
  FFarbe:=col;
end;


procedure TForm1.btnClick(Sender: TObject);
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create('rot');
end;
Option 2:
Du übergibst keine Farbe und nimmst "rosa"

Delphi-Quellcode:
constructor TAuto.Create;
begin
  inherited Create;
  FFarbe:='rosa';
end;


procedure TForm1.btnClick(Sender: TObject);
var
  LKW: TAuto;
begin
  LKW:=TAuto.Create;
  LKW.Farbe:='rot';
end;
vielleicht in dem Zusammenhang auch für dich interessant sind folgende Stichwörter:
overload
override
reintroduze


Gruß
angos

Hallo!
Die "Option 2" war gemeint.
War ein "copyandpaste"-Fehler von mir (siehe auch meine Antwort an freak4fun).
Nur funktioniert das leider nicht.

freak4fun 7. Jun 2010 14:25

AW: Eigener Konstruktor
 
Hast du mal einen Breakpoint gesetzt und bist da durchgestept? Was bedeutet "Nur funktioniert das leider nicht." Welche Farbe ist gesetzt? Wie prüfst du ob es "funktioniert"?

FriendOfDelphi 7. Jun 2010 14:44

AW: Eigener Konstruktor
 
Zitat:

Zitat von freak4fun (Beitrag 1026370)
Hast du mal einen Breakpoint gesetzt und bist da durchgestept? Was bedeutet "Nur funktioniert das leider nicht." Welche Farbe ist gesetzt? Wie prüfst du ob es "funktioniert"?

Ja, habe ich.
Folgender Effekt:
Wenn ich den Quellcode komplett, also Klassendefinition und die Verwendung der Klasse in eine Unit schreibe, dann kann ich einen Breakpoint im Konstruktor setzen und dieser wird auch durchlaufen.
Wenn ich, wie von mir bevorzugt, die Klasse in einer eigenen Unit definiere und diese in einer anderen Unit nur verwenden will, dann nimmt der Compiler die Breakpoints im Konstruktor weg, so dass ich dort keinen mehr setzen kann.
Um zu überprüfen welche Farbe gesetzt wurde, verwende ich einfach ein
Delphi-Quellcode:
ShowMessage(LKW.Farbe);
.
Das Feld ist aber immmer leer, also ''.
Es sei denn, ich verwende
Delphi-Quellcode:
LKW.Farbe:='rot';
.
Dann wird die Farbe "rot" gesetzt.

mkinzler 7. Jun 2010 14:46

AW: Eigener Konstruktor
 
Befindet sich die Unit (bzw. deren Pfad) im Suchpfad?

uligerhardt 7. Jun 2010 14:47

AW: Eigener Konstruktor
 
Zitat:

Zitat von FriendOfDelphi (Beitrag 1026376)
Wenn ich den Quellcode komplett, also Klassendefinition und die Verwendung der Klasse in eine Unit schreibe, dann kann ich einen Breakpoint im Konstruktor setzen und dieser wird auch durchlaufen.
Wenn ich, wie von mir bevorzugt, die Klasse in einer eigenen Unit definiere und diese in einer anderen Unit nur verwenden will, dann nimmt der Compiler die Breakpoints im Konstruktor weg, so dass ich dort keinen mehr setzen kann.

Das dürfte daran liegen, dass du den Konstruktor als privat deklariert hast. Wenn du ihn von außen - insbesondere aus einer anderen Unit - aufrufen willst, wäre public angesagt.

Jens Hartmann 7. Jun 2010 14:48

AW: Eigener Konstruktor
 
Hallo,

ich bin mir nicht sicher, aber in einer anderen Unit kann es nicht gehen, weil der constructor Privat ist...

Delphi-Quellcode:
type
  TAuto = class(TObject)
  private
    FFarbe: string;
    procedure SetFarbe(Farbe: string);
    constructor Create(col: string);//hier eventuell mal schauen.
  public
    property Farbe: string read FFarbe write SetFarbe;
end;
EDIT... Zu spät...

Gruß Jens

FriendOfDelphi 7. Jun 2010 14:58

AW: Eigener Konstruktor
 
Zitat:

Zitat von mkinzler (Beitrag 1026379)
Befindet sich die Unit (bzw. deren Pfad) im Suchpfad?

Die Unit ist im selben Projekt.
Der Compiler meckert nicht.
Die Unit wird also gefunden.

freak4fun 7. Jun 2010 15:06

AW: Eigener Konstruktor
 
Zitat:

Zitat von FriendOfDelphi (Beitrag 1026389)
Zitat:

Zitat von mkinzler (Beitrag 1026379)
Befindet sich die Unit (bzw. deren Pfad) im Suchpfad?

Die Unit ist im selben Projekt.
Der Compiler meckert nicht.
Die Unit wird also gefunden.

DIe Unit wird gefunden, aber der Constructor nicht. Wenn du eine Klasse in einer Unit hast, kann da alles auf den Private-Bereich zugreifen. Wenn du nun aber die Klasse in eine andere Unit schreibst, kann die erste Unit nicht mehr auf den Private-Bereich der nun ausgelagerten Klasse zuegreifen. Daraus folgt, das du den Constructor als Public deklarieren musst. Dann wird auch der Breakpoint nicht mehr entfernt. ;)

FriendOfDelphi 7. Jun 2010 15:08

AW: Eigener Konstruktor
 
Ok. Das war's.
Der Konstruktor muss public sein.

Ist das denn so "richtiger" Quellcode?
Ich meine gelesen zu haben, dass man das so nicht machen soll, oder?

DeddyH 7. Jun 2010 15:24

AW: Eigener Konstruktor
 
Was soll man wie nicht machen? Vordefinierte Werte im Konstruktor zuweisen? Dafür ist der doch u.a. da.

Sir Rufo 7. Jun 2010 15:24

AW: Eigener Konstruktor
 
Zitat:

Zitat von FriendOfDelphi (Beitrag 1026395)
Ok. Das war's.
Der Konstruktor muss public sein.

Ist das denn so "richtiger" Quellcode?
Ich meine gelesen zu haben, dass man das so nicht machen soll, oder?

Man macht es halt so, dass es funktioniert. Dann ist das "richtiger" Quellcode.

und wenn beim Create der hinterlegte Code ausgeführt werden soll, dann muss der constructor public sein.

Jens Hartmann 7. Jun 2010 15:25

AW: Eigener Konstruktor
 
Hallo,

z.B.
privat, ist nur in der eigenen Unit sichtbar.
public im gesamten Projekt.

Man sollte also als privat deklarieren, was nach außen hin nicht sichtbar sein soll, z.B. Methoden, die in der Klasse selbst benötigt werden. Da du den Constructor ja außen benötigen tust, muss er public sein.

Eine Aufstellung dieser Deklarationen findest du in der Hilfe von Delphi...

Gruß Jens

mkinzler 7. Jun 2010 15:29

AW: Eigener Konstruktor
 
Ein constructor sollte immer public sein. Soll die Klasse nur in einer Unit verwendbar sein dann deklariert man sie halt unter Implementation

Tryer 7. Jun 2010 16:07

AW: Eigener Konstruktor
 
Und falls SetFarbe irgendwas "wichtiges" macht, dann würde ich einfach auch im Constructor SetFarbe('rosa') bzw. Farbe := 'rosa' aufrufen statt nur das Feld FFarbe zu setzen.

Grüsse, Dirk

DeddyH 7. Jun 2010 16:12

AW: Eigener Konstruktor
 
Jepp, es kommt eben darauf an, ob ein evtl. Setter durchlaufen werden soll (dann weist man der Property einen Wert zu) oder nicht (dann greift man direkt auf das Feld zu).

mkinzler 7. Jun 2010 16:22

AW: Eigener Konstruktor
 
GGf noch eine Konstruktor mit entsprechendem Parameter

eragon123 7. Jun 2010 16:55

AW: Eigener Konstruktor
 
Naja ich bin mir da jetzt nicht sicher, deshalb ist das hier auch eine halbe Frage: aber er setzt doch
Delphi-Quellcode:
Farbe: string read FFarbe write Setfarbe
. Kann er dann im Konstruktor überhaubt Farbe := .... benutzen? Muss hier jetzt nicht auch die gerade deklarierte Setfarbe Methode genutzt werden? Oder geht das im Konstruktor noch gar nicht?

xZise 7. Jun 2010 16:57

AW: Eigener Konstruktor
 
Hmmm kommt mir irgendwie bekannt vor...

[edit]Wegen Roten Kasten (falls man den so nennen darf): Du kannst ja darauf zugreifen, wenn der ursprüngliche Konstruktor bereits ausgeführt wurde. Also sowas wie inherited Create[/edit]

MfG
Fabian

mkinzler 7. Jun 2010 18:31

AW: Eigener Konstruktor
 
Auf private Felder kann man innerhalb der Unit zugreifen bzw. bei strict private nur innerhalb der Klasse. Bei beidem wäre hier die Bedingung erfüllt


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:37 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz