Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Constructor from Instance (https://www.delphipraxis.net/214454-constructor-instance.html)

Stefan1286b 15. Jan 2024 06:55

Constructor from Instance
 
Guten Tag.
Weiß jemand wie man einen Constructor von einer Instanz aufruft?
Zum verstehen eine Kleines Beispiel:
Code:
type
TAnimal = class
public
 Name:String;
end;

TDog = class(TAnimal)
public
Hairs:Integer;
end;

TCat = class(Tanimal)
public
Color:Integer;
end;




var
 Animal1,Animal2:TAnimal;
begin
 Animal1 := TDog.Create;

 //Some Code

 Animal2 := Animal1.Create; // << Das funktioniert nicht. Animal1 wird überschrieben.
 Animal2 := Animal1.Class.Create; // << Auch das funktioniert nicht. Wird dann ein TObject.
Die eigentliche Klasse ist von TPersistent abgeleitet und hat schon funktionstüchtig AssignTo mittels RTTI implementiert.

Und gelegentlich muss ich von einer Instanz erstellen.

Ich an folgendes gedacht:

Code:
type
TAnimal = class
public
 Name:String;
 procedure New:TAnimal; virtual; abstract;
end;

TDog = class(TAnimal)
public
Hairs:Integer;
procedure New:TAnimal; override;
end;

TCat = class(Tanimal)
public
Color:Integer;
procedure New:TAnimal; override;
end;

procedure TDogNew:TAnimal;
begin
 Result := TDog.Create;
end;


var
 Animal1,Animal2:TAnimal;
begin
 Animal1 := TDog.Create;

 //Some Code

 Animal2 := Animal1.New;
Aber denke das geht vielleicht auch einfacher.

Vielen Dank im vorraus.

uligerhardt 15. Jan 2024 07:14

AW: Constructor from Instance
 
Als erstes würde ich TAnimal mal einen virtuellen Konstruktor verpassen.

Und die Variante mit
Delphi-Quellcode:
Class
müsste prinzipiell funktionieren, wenn du etwas ergänzt:
Delphi-Quellcode:
type
  TAnimalCLass = class of TAnimal; // Stichwort "Class reference" oder "Metaklasse"
Animal2 := TAnimalCLass(Animal1.Class).Create;
(freihändig hingetippt)

TiGü 15. Jan 2024 07:39

AW: Constructor from Instance
 
Jetzt noch ClassType statt Class und dann geht's! :thumb:

Delphi-Quellcode:
type
    TAnimal = class
    public
        Name: String;
    end;

    TDog = class(TAnimal)
    public
        Hairs: Integer;
    end;

    TCat = class(TAnimal)
    public
        Color: Integer;
    end;

    TAnimalClass = class of TAnimal;

var
    Animal1, Animal2: TAnimal;

begin

    try
        Animal1 := TDog.Create;

        Animal2 := TAnimalClass(Animal1.ClassType).Create;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;

end.

uligerhardt 15. Jan 2024 07:46

AW: Constructor from Instance
 
Zitat:

Zitat von TiGü (Beitrag 1531889)
Jetzt noch ClassType statt Class

Äh, ja :oops:
Zitat:

Zitat von TiGü (Beitrag 1531889)
und dann geht's! :thumb:

... und sogar ohne virtuellen Konstruktor :shock:

himitsu 15. Jan 2024 09:28

AW: Constructor from Instance
 
Zitat:

Delphi-Quellcode:
Animal1.Create; // << Das funktioniert nicht. Animal1 wird überschrieben.

Natürlich, weil du hier den Constructor als Funktion/Methode aufrufst, auf einer bestehenden Objekt-Instanz.

Man benutzt zum Erstellen NIEMALS keine Variable, sondern immer den Typ.

ALSO
Delphi-Quellcode:
//Animal2 := Animal1.Create; {NEIN}
Animal2 := TAnimal.Create;
denn sowas will und sollte man, nach Möglichkeit, nicht machen:
Delphi-Quellcode:
Animal2 := TAnimal(TAnimal.NewInstance);
Animal2.Create;

Zitat:

Jetzt noch ClassType ...
Ja, Ob jun direkt den Klassentyp verwenden, oder über eine KlassenTyp-Varialbe (TClass) ... Hauptsache eine Klasse und nicht das Objekt.


Dass es dir das Objekt in Variable Animal1 überschrieben hat, ist korrekt.
Mehr Spaß hättest du mit
Delphi-Quellcode:
Animal2 := Animal2.Create;
, denn diese Variable war noch nicht initialisiert und es hätte hoffentlich eine schöne Exception gegeben. :angle2:

Zitat:

Delphi-Quellcode:
Animal2 := TAnimalClass(Animal1.ClassType).Create;

Und nun nur nochmal aus Spaß, auch hier geht es mit getrennter Initialisierung/Speicherreservierung und nachträglichem Constructor.
Delphi-Quellcode:
Animal2 := TAnimal(Animal1.NewInstance);
Animal2.Create;

Stefan1286b 16. Jan 2024 12:01

AW: Constructor from Instance
 
Delphi-Quellcode:
Animal2 := TAnimalClass(Animal1.ClassType).Create;
Das funktioniert einwandfrei. Vielen Dank

himitsu 16. Jan 2024 12:28

AW: Constructor from Instance
 
Zitat:

Zitat von Stefan1286b (Beitrag 1531999)
Delphi-Quellcode:
Animal2 := TAnimalClass(Animal1.ClassType).Create;

Will man den Constructor überschreiben, dann muß bei sowas natürlich spätestens in diesem Basistyp das als VIRTUAL (oder DYNAMIC) deklariert sein, und in den Nachfahren natürlich OVERRIDE.

Stefan1286b 16. Jan 2024 19:25

AW: Constructor from Instance
 
Ja, das ist richtig.

uligerhardt hatte zwar geschrieben dass es auch ohne geht.

Das Allerdings nur bedingt und damit nicht richtig.
Man kann alle Felder benutzen aber der abgeleitete Constructor wird nicht aufgerufen.
Im Beispiel gab es keinen. Deswegen ist es nicht aufgefallen.
Virtueller und in abgeleiteter Klasse überschriebener Constructor und es funktionier einwandfrei.

Wenn man solche speziellen Sachen macht muss man natürlich noch mehr darauf achten, dass nachher alles wieder freigegeben wird.

Das war bei mir aber gegeben durch:

Delphi-Quellcode:
type
  TAnimalList = class(TObjectList<TAnimal>)
  public
    constructor Create; reintroduce;
  end;

constructor TAnimalList.Create;
begin
  inherited Create(true); //AOwnsObjects
end;

himitsu 16. Jan 2024 19:53

AW: Constructor from Instance
 
Bei der Liste muß es nicht sein,
aber wenn TDog und TCat einen eigenen Constructor haben sollen.

Wie bei den TComponent-Nachfahren, welche man auf die Form pappen kann und wo der DFM-Loader natürlich nur TComponent kennt.

Rollo62 17. Jan 2024 07:05

AW: Constructor from Instance
 
Zitat:

Zitat von Stefan1286b (Beitrag 1531999)
Delphi-Quellcode:
Animal2 := TAnimalClass(Animal1.ClassType).Create;
Das funktioniert einwandfrei. Vielen Dank

Sorry, aber warum will man sowas überhaupt machen, mir fällt dazu kaum ein Use-Case ein.
Bestenfalls wäre ein duplizieren einer Instanz, wozu ich dann immer eine explizite Methode ".Clone" dafür anlegen würde, die auch was entsprechend vorbereiten kann.

Der einzige, mögliche Grund, der mit einfällt, könnte sein,
wenn man von einer geschlossenen 3rd-Party Library nur eine Instanz bekommt, aber keinen Zugriff auf die Klassendefinition oder SourceCodes hat.
Dann würde ich aber versuchen diese 3rd-Party Komponente so schnell wie möglich rauszuwerfen.

Bitte klärt mich auf, wenn dafür doch wichtige Anwendungen gibt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:34 Uhr.
Seite 1 von 2  1 2      

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