Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Klassen constructor Aufrufen (https://www.delphipraxis.net/192258-klassen-constructor-aufrufen.html)

bernhard_LA 3. Apr 2017 21:38

Klassen constructor Aufrufen
 
ich habe eine Komponente die sich von TImage ableitet.
Wenn ich die Komponente zur Laufzeit in meiner Anwendung erzeuge kann ich einen von beiden class constructoren direkt aufrufen. Es spielt alles wie es soll.

Wenn ich die Komponente nun installiere und auf mein Formular ziehe, dann wird der Konstruktor nicht aufgerufen, ich bekomme einen Fehler bei nicht initialisieren lokalen Variablen meiner Klasse.

Welcher Constructor wird ausgeführt wenn ich meine Komponente auf ein Form ziehe ?



Delphi-Quellcode:
TPImage = class(TImage)
  private
    { Private-Deklarationen }
   

  protected
    { Protected-Deklarationen }

    BasicInit: Boolean;

  public
    { Public-Deklarationen }

    constructor create(xpixel, ypixel: Integer); overload;

    constructor create(aOwner: TWinControl); overload;

    destructor destroy; override;

...

end;

Uwe Raabe 3. Apr 2017 22:01

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von bernhard_LA (Beitrag 1366319)
Welcher Constructor wird ausgeführt wenn ich meine Komponente auf ein Form ziehe ?

Der in
Delphi-Quellcode:
TComponent
definiert ist. Den musst du überschreiben, wenn das was werden soll.

himitsu 3. Apr 2017 22:02

AW: Klassen constructor Aufrufen
 
Rate mal, warum TComponent einen virtuellen Contructor hat. :zwinker:

bernhard_LA 4. Apr 2017 08:50

AW: Klassen constructor Aufrufen
 
mit dem Schlüsselwort override komme ich leider auch nicht weiter

Delphi-Quellcode:
    //  diesen Ausführen wenn ich K. zur Laufzeit erzeuge
    constructor create(xpixel, ypixel: Integer); overload;
    //  diesen Ausführen wenn ich K. auf mein Form gezogen habe
    constructor create(aOwner: TWinControl); override; overload;


Fehlermeldung :

[dcc32 Error] Unit_TPl.pas(97): E2037 Declaration of 'Create' differs from previous declaration

Lemmy 4. Apr 2017 09:01

AW: Klassen constructor Aufrufen
 
das sollte eher so aussehen:

Delphi-Quellcode:
 
    constructor create(aOwner: TWinControl; xpixel, ypixel: Integer); override; reintroduce;
und dann ein inherited create(aowner)....

Neutral General 4. Apr 2017 09:02

AW: Klassen constructor Aufrufen
 
Überschriebene Methoden müssen die gleiche Signatur haben wie die virtuelle in der Basisklasse. D.h.:
Delphi-Quellcode:
constructor Create(AOwner: TComponent); override;
Zitat:

Zitat von Lemmy (Beitrag 1366341)
das sollte eher so aussehen:
Delphi-Quellcode:
 
    constructor create(aOwner: TWinControl; xpixel, ypixel: Integer); override; reintroduce;
und dann ein inherited create(aowner)....

Der Konstruktor wird aber auch nicht aufgerufen wenn du das Image aufs Formular ziehst.

Uwe Raabe 4. Apr 2017 09:24

AW: Klassen constructor Aufrufen
 
Dein Interface müsste dann in etwa so aussehen:
Delphi-Quellcode:
    constructor Create(AOwner: TComponent); overload; override;
    constructor Create(xpixel, ypixel: Integer); reintroduce; overload;
    constructor Create(aOwner: TWinControl); reintroduce; overload; // wobei das hier eventuell Probleme bereitet, das TWinControl ja ebenfalls ein TComponent ist.
Die eigentliche Arbeit steckt aber in den Implementierungen, zu denen wir aber so nicht viel sagen können.

DeddyH 4. Apr 2017 10:46

AW: Klassen constructor Aufrufen
 
Zitat:

Delphi-Quellcode:
constructor Create(aOwner: TWinControl); reintroduce; overload; // wobei das hier eventuell Probleme bereitet, das TWinControl ja ebenfalls ein TComponent ist.

Wenn man es gar nicht anders hinbekommt:
Delphi-Quellcode:
constructor Create(aOwner: TWinControl; NotNeededDummy: integer = 0); reintroduce; overload;
Aber sowas würde ich nur im alleräußersten Notfall und mit Bauchgrimmen implementieren.

bernhard_LA 4. Apr 2017 10:55

AW: Klassen constructor Aufrufen
 
die Konstruktoren habe ich wie folgt abgeändert :


Delphi-Quellcode:
 
TPImage = class(TImage)
  private

  public
    { Public-Deklarationen }


    constructor create(aOwner: TComponent); overload; override;

    constructor create(aOwner: TComponent; xpixel, ypixel: Integer);  reintroduce; overload;

    ....

constructor TPImage.create(aOwner: TComponent);
begin
  inherited create(aOwner);

  createPParams(nil);
end;

constructor TPImage.create(aOwner: TComponent ; xpixel, ypixel: Integer);
begin
  // object Defaults
  inherited create(aOwner);

  Self.Height := ypixel;
  Self.Width := xpixel;

  // user code
  createPParams(nil);

end;

Wenn ich die installierte Komponente jetzt auf das Formular ziehe sieht es gut aus ( muss noch mehr testen)
allerdings funktioniert das Erzeugen zur Laufzeit jetzt nicht mehr

also

Delphi-Quellcode:
 //   Größe des Bilder möchte ich via align einstellen
 FPI := TPImage.create(Panel1);
 //  ich gebe die Größe des Bildes vor ...
 FPI := TPImage.create(Panel1,300,300);

dann wird auf meinem Panel nichts mehr anzeigt , ich muss dann nochmals

FPI.Parent := Panel1;

einfügen. Ich dachte die Info bekommt die Class schom beim Ausführen des KOnstruktors

Mavarik 4. Apr 2017 11:04

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von bernhard_LA (Beitrag 1366360)

dann wird auf meinem Panel nichts mehr anzeigt , ich muss dann nochmals

FPI.Parent := Panel1;

einfügen. Ich dachte die Info bekommt die Class schom beim Ausführen des KOnstruktors

Nein... Das musst Du immer machen...

Es könnte ja

Delphi-Quellcode:
AInstance := TFoo.Create(Form1,10,10);
AInstance.Parent := Panel1;
sein...

himitsu 4. Apr 2017 11:42

AW: Klassen constructor Aufrufen
 
Komponenten im FormDesigner bekommen als Owner immer die Form und als Parent das, worauf sie liegen.

Aber du kannst im Constructor ja dennoch Parent = Owner setzen, für denn Fall, dass die Komponente manuell erstellt wird.
(lässt sich ja nach dem Constructor neu zuweisen, wenn es doch ein anderer Parent werden soll)

Man kann über Self.ComponentState (im Constructor siehe Owner.ComponentState) rausbekommen, ob die Komponente grade im FormDesigner liegt, oder ob soe grade aus einer DFM geladen wird.
Nur der TForm-Constructor ist ein Sonderfall, wenn dieser über Application.CreateForm erstellt wird, denn da ist der Zustannd bereits im Constructor bekannt. Leider waren Her Wirth und Borland nicht nett genug, das auch im TReader (DFM-Loader) zu machen.

Mavarik 4. Apr 2017 12:18

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von bernhard_LA (Beitrag 1366319)
Welcher Constructor wird ausgeführt wenn ich meine Komponente auf ein Form ziehe ?

Nochmal zurück zu dieser Frage... Man möge mich korrigieren, wenn ich falsch liege...

Wenn ich eine Object erzeuge das ich von einem anderen Object ableite schreibe ich i.d.R. nicht override...

Beispiel:

Delphi-Quellcode:
type
  TMyButton = class(TButton)
    public
      Constructor Create(AOwner : TComponent);
  end;
Denn mit einem TMyButton.Create wird mein constructor aufgerufen hier mache ich den inherited

Warum also ein override?

Weil nicht mein Constructor aufgerufen wird?

Anders bei Methoden. Siehe docwiki!

Uwe Raabe 4. Apr 2017 13:04

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von Mavarik (Beitrag 1366384)
Warum also ein override?

Das kommt darauf an, was du erreichen willst. Solange du immer nur TMyButton.Create aufrufst, funktioniert das. Sobald aber das Streaming-System oder der IDE-Formular-Designer ins Spiel kommen, ist dein Constructor außen vor und wird nicht aufgerufen. Wie gesagt, das kann so gewünscht sein - ist es in der Regel aber nicht.

Der Sinn von virtuellen Konstruktoren ist ja genau der, daß sie auch aufgerufen werden können, wenn dem Aufrufenden die tatsächliche Klasse nicht bekannt ist.

Fritzew 4. Apr 2017 13:19

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von Mavarik (Beitrag 1366384)
Zitat:

Zitat von bernhard_LA (Beitrag 1366319)
Welcher Constructor wird ausgeführt wenn ich meine Komponente auf ein Form ziehe ?

Nochmal zurück zu dieser Frage... Man möge mich korrigieren, wenn ich falsch liege...

Wenn ich eine Object erzeuge das ich von einem anderen Object ableite schreibe ich i.d.R. nicht override...

Beispiel:

Delphi-Quellcode:
type
  TMyButton = class(TButton)
    public
      Constructor Create(AOwner : TComponent);
  end;

Das kommt aber ne Warnung wenn Die neue Klasse von TComponent abgeleitet ist. Aus diesem Grund werden bei uns eigentlich fast alle Warnungen als Fehler behandelt, dann geht so etwas auf keinen Fall unter

Mavarik 4. Apr 2017 13:40

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1366394)
Sobald aber das Streaming-System oder der IDE-Formular-Designer ins Spiel kommen, ist dein Constructor außen vor und wird nicht aufgerufen.

Ja genau - das wollte ich eigentlich damit sagen... :stupid:

Zitat:

Zitat von Uwe Raabe (Beitrag 1366394)
Der Sinn von virtuellen Konstruktoren ist ja genau der, daß sie auch aufgerufen werden können, wenn dem Aufrufenden die tatsächliche Klasse nicht bekannt ist.

Perfekt... Warum hatte ich das nicht geschrieben? OK ich hole mir erst nen Kaffee...

:thumb:

Immer wenn das Telefon klingelt, sollte ich meine Post vor dem senden erst nochmal lesen...

HolgerX 4. Apr 2017 15:39

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von bernhard_LA (Beitrag 1366360)
Delphi-Quellcode:
constructor TPImage.create(aOwner: TComponent);
begin
  inherited create(aOwner);

  createPParams(nil);
end;

constructor TPImage.create(aOwner: TComponent ; xpixel, ypixel: Integer);
begin
  // object Defaults
  inherited create(aOwner);

  Self.Height := ypixel;
  Self.Width := xpixel;

  // user code
  createPParams(nil);

end;

Da du in deinem erweiterten constructor den originalen per inherited aufrufst, kannst Du dir in deinem erweiterten das
Delphi-Quellcode:
  // user code
  createPParams(nil);
sparen!


Also:

Delphi-Quellcode:
constructor TPImage.create(aOwner: TComponent);
begin
  inherited create(aOwner);

  createPParams(nil);
end;

constructor TPImage.create(aOwner: TComponent ; xpixel, ypixel: Integer);
begin
  // object Defaults
  inherited create(aOwner);

  Self.Height := ypixel;
  Self.Width := xpixel;
end;

Neutral General 4. Apr 2017 15:54

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von bernhard_LA (Beitrag 1366360)
Ich dachte die Info bekommt die Class schom beim Ausführen des KOnstruktors

Owner und Parent sind zwei unterschiedliche Dinge.
Der Owner verwaltet die Instanz des Controls und gibt sie frei wenn er selbst freigegeben wird.
Das Parent ist das Control auf dem das erstellte Control platziert werden soll.

Uwe Raabe 4. Apr 2017 16:15

AW: Klassen constructor Aufrufen
 
Zitat:

Zitat von HolgerX (Beitrag 1366418)
Da du in deinem erweiterten constructor den originalen per inherited aufrufst, kannst Du dir in deinem erweiterten das
Delphi-Quellcode:
  // user code
  createPParams(nil);
sparen!

Da wäre ich jetzt nicht so sicher! Du rufst ja explizit das inherited Create auf und nicht das der aktuellen Klasse.

HolgerX 4. Apr 2017 17:18

AW: Klassen constructor Aufrufen
 
Hmm..


Wäre es dann nicht besser, das inherited weg zu lassen?
Dann würden beide Aufrufe zur selben 'Basis' passen, ohne immer alles aus dem Einen im Anderen wieder nachziehen zu müssen.

himitsu 4. Apr 2017 17:53

AW: Klassen constructor Aufrufen
 
[edit] Jupp, weg damit.

Zitat:

Zitat von HolgerX (Beitrag 1366418)
Da du in deinem erweiterten constructor den originalen per inherited aufrufst, kannst Du dir in deinem erweiterten das
Delphi-Quellcode:
  // user code
  createPParams(nil);
sparen!

Dann sollte man da aber das Inherited weglassen, denn damit wird der Vorfahr aufgerufen, wo das nicht drin ist,

also:
Delphi-Quellcode:
constructor TPImage.Create(aOwner: TComponent);
begin
  inherited; //inherited Create(aOwner);  // wenn es gleich ist (Name und Parameter, dann muß man es nicht angeben) ... finde ich übersichtlicher, da man so weiß, dass nur der direkte Vorfahre gemeint ist
  createPParams(nil);
end;

constructor TPImage.Create(aOwner: TComponent; xpixel, ypixel: Integer);
begin
  // object Defaults
  Create(aOwner); // inherited Create(aOwner); // hier ohne Inherited, wenn man den "Eigenen" meint

  Self.Height := ypixel;
  Self.Width := xpixel;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:11 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