Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Objekt anhand der Klassenbezeichnung erzeugen (https://www.delphipraxis.net/115339-objekt-anhand-der-klassenbezeichnung-erzeugen.html)

SWE 10. Jun 2008 16:13


Objekt anhand der Klassenbezeichnung erzeugen
 
Gibt es die Möglichkeit ein Objekt anhand der Klassenbezeichnung zu erzeugen?
Beispiel:
Ich habe die Klassentypen TMeinObjekt1 und TMeinObjekt2.
Jetzt bräuchte ich eine Funktion die einen String entgegennimmt z.B. 'TMeinObjekt1' und eine Objektinstanz vom entsprechenden Typ zurückliefert.
Aber bitte nicht so:
Delphi-Quellcode:
   if str = 'TMeinObjekt1' then
        Result := TMeinObjekt1.Create();
Da gibt es doch bestimmt eine intelligente Lösung die für alle Objekttypen gilt, oder?
Fragt mich bitte nicht, wofür ich es brauch. Ich weiß es selbst noch nicht, sondern will es erst mal nur so wissen.

Danke schon mal.

Luckie 10. Jun 2008 16:39

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Sollte es sich um eine Komponente handlen, gibt es Delphi-Referenz durchsuchenFindComponent.

Apollonius 10. Jun 2008 16:44

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Hier geht es um Klassen, nicht Instanzen.

Einen sauberen Weg gibt es nicht, aber hier im Forum geistert eine Unit herum, mit der man alle Typinformationen in einem Modul auflisten kann. Damit ist es dann trivial, weil in den Typinformationen der Klasse auch die TClass gespeichert ist.

Luckie 10. Jun 2008 16:50

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Oh, sorry.

uligerhardt 10. Jun 2008 17:53

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Musst du wirklich alle Klassen behandeln oder nur welche, die du selber schreibst? In letzterem Falle würde ich einen Mechanismus a la RegisterClass machen. Schau dir mal an, wie das in der VCL implementiert ist.

HTH,
Uli.

Hawkeye219 10. Jun 2008 17:58

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Hallo,

shmia zeigt in einem Beitrag zur Code-Library, wie man die Funktion Delphi-Referenz durchsuchenRegisterClass und Delphi-Referenz durchsuchenFindClass einsetzen kann.

Gruß Hawkeye

SWE 11. Jun 2008 07:42

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Super, vielen Dank. Klappt wunderbar und reicht mir!

So ungefähr geht's:

Delphi-Quellcode:
// Test-Objekt
TMeinObjekt1 = class (TPersistent)
public
    strName : String;
end;

...

initialization
  // Klasse registrieren
  RegisterClass(TMeinObjekt1);
end;      

...

// Test-Prozedur
procedure Test();
var
    cls : TPersistentClass;
    obj : TObject;
begin
    // Klassenreferenz ermitteln
    cls := FindClass('TMeinObjekt1');
    // Objekt-Instanz erzeugen
    obj := cls.Create();
    // Da nicht das konkrete Objekt erzeugt wurde, wird hier gecasted
    TMeinObjekt1(obj).strName := 'Hallo';
    // Test-Ausgabe
    ShowMessage(TMeinObjekt1(obj).strName);
end;

Pascal P 20. Jun 2008 14:58

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Hi zusammen!
Ich versuche gerade ähnliches zu machen. Allerdings habe ich noch ein Problem.
Das Objekt erstellen ist ja so kein Problem. Allerdings wird nur mein Constructor der Basisklasse aufgerufen und nicht der des eigentlichen Objektes.

Delphi-Quellcode:
TBaseObjekt = class (TPersistent)
public
    strName : String;
    constructor Create; overload;
end;

TBaseObjectClass = class of TBaseObject;

TExtendedObjekt = class (TBaseObjekt)
public
    constructor Create; overload;
end;

constructor TBaseObjekt.Create;
begin
  Self.strName := 'Base';
end;

constructor TExtendedObjekt.Create;
begin
  Self.strName := 'Extendet';
end;

procedure Test();
var
    cls : TPersistentClass;
    obj : TBaseObject;
begin
    // Klassenreferenz ermitteln
    cls := FindClass('TExtendedObjekt');
    // Objekt-Instanz erzeugen
    obj := TBaseObjectClass( cls ).Create();
    // Test-Ausgabe
    ShowMessage(TExtendedObjekt(obj).strName);
    // Die Ausgabe sollte dann Base sein
end;
Das Baseobjekt stellt bei mir eine eigene Classroot dar von der ich alles ableite. Ich weiss lediglich mittels eines Strings, hier TExtendedObject' welches Object ich erzeugen muss/will. Also kann ich mich nur auf den allgemeinen kleinsten Nenner, die TBaseObject, beziehen. Das erstellte Objekt ist auch vom Typ TExtendedObject. Jedoch eben nicht mit den für dieses Object initialisierten Werten, sondern denen der Basisklasse.

Hoffe konnte verständlich machen um was es mir geht und hoffe auf Hilfe.
Liebe Grüsse Pascal

Hansa 20. Jun 2008 15:14

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Was macht nochmal das overload ? :gruebel: Normaler Weg wäre override in der Deklaration und eventuell inherited aufrufen.

Pascal P 20. Jun 2008 15:21

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Ok, das Overload gehört da garnicht hin. Das war wohl zuviel kopiert und rumgebastelt.
Dient aber dazu um Methoden zu überladen.

Delphi-Quellcode:
  procedure MeineMethode( str : String );
  procedure MeineMethode( int : Integer ); overload;

  procedure MeineMethode( str : String );
  begin
    ShowMessage( str );
  end;

  procedure MeineMethode( int : Integer );
  begin
    MeineMethode( IntToStr( int ) );
  end;
Mehr macht das garnicht.

Mit inherited arbeite ich auch. Nur passiert eben folgendes. Ich initiiere ein Objekt einer Klasse die ich als String angebe (wenn sie denn gefunden wird).
Nur der Constructor wird eben von der Basisklasse verwendet. Ich kann ja zum derzeitigen Punkt nicht wissen um welchen Typ Klasse es sich dabei handelt.

shmia 20. Jun 2008 15:28

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Zitat:

Zitat von Pascal P
Allerdings wird nur mein Constructor der Basisklasse aufgerufen und nicht der des eigentlichen Objektes.

Du musst den Konstruktor virtuell machen!
Aus diesem Grund ist auch der Konstruktor von TComponent virtuell. Ansonsten würde das dynamische Laden von Komponenten aus dem DFM-Resourcen nicht funktionieren.

Hansa 20. Jun 2008 15:29

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Hilfe gut und schnell abgekupfert. :mrgreen: Sehe gerade in der Test-Prozedur, wo wird denn da überhaupt das gewünschte Objekt created ? Erzeuge das mal lieber direkt. Also so :
Delphi-Quellcode:
obj := TExtendedClass.Create;

Vjay 20. Jun 2008 15:39

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Aber müsste nicht der neue constructor den alten trotzdem (rein logisch gesehen) verdecken?

Hansa 20. Jun 2008 15:48

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Mit override wird der verdeckt. Den Constructor der Basisklasse kann man dann mit inherited explizit aufrufen.

shmia 20. Jun 2008 15:55

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Zitat:

Zitat von Vjay
Aber müsste nicht der neue constructor den alten trotzdem (rein logisch gesehen) verdecken?

Nicht, wenn der neue Konstruktor mit override deklariert wurde.
Dann muss aber auch die Signatur, also Anzahl und Datentypen der Übergabeparameter, immer so sein, wie das in der Basisklasse einmal festgelegt wurde.
Delphi-Quellcode:
TBaseObject = class(...)
  constructor Create; virtual;
  ...
end;
TExtendedObject = class(TBaseObject)
  constructor Create; override;
  ...
end;
TExtendedObject2 = class(TBaseObject)
  constructor Create; override;
  ...
end;
Man kann sich das alles aus der TComponent Hierarchie abschauen.

Pascal P 20. Jun 2008 16:23

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Irgendwie muss ich grad voll ends auf dem Schlauch stehen. Habe mal eben die Änderung mit virtual gemacht. gehen tut es aber noch immer nciht.
Mein Programmcode sieht nun in etwa so aus.

Delphi-Quellcode:
TBaseObjekt = class (TPersistent)
public
    strName : String;
    constructor Create; virtual;
end;

TBaseObjectClass = class of TBaseObject;

TExtendedObjekt = class (TBaseObjekt)
public
    constructor Create;
end;

constructor TBaseObjekt.Create;
begin
  Self.strName := 'Base';
end;

constructor TExtendedObjekt.Create;
begin
  Self.strName := 'Extendet';
end;

procedure Test();
var
    cls : TPersistentClass;
    obj : TBaseObject;
begin
    // Klassenreferenz ermitteln
    cls := FindClass('TExtendedObjekt');
    // Objekt-Instanz erzeugen
    obj := TBaseObjectClass( cls ).Create();
    // Test-Ausgabe
    ShowMessage(TExtendedObjekt(obj).strName);
    // Die Ausgabe sollte dann Base sein
end;
Funktionieren tut es noch immer wie davor. Es wird der Constructor der Basisklasse verwendet und nicht der der eigentlichen Klasse.

shmia 20. Jun 2008 16:26

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Du hast das override beim Konstruktor der abgeleiteten Klasse vergessen!!
Delphi-Quellcode:
TExtendedObjekt = class (TBaseObjekt)
public
    constructor Create; override; // <==
end;

Pascal P 20. Jun 2008 16:30

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Argh, vor lauter Bäumen den Wald nicht mehr gesehen. Okey, danke nochmals. In einem kleinen Testprogramm funktioniert es jetzt.
Werd es dann mal versuchen vollends zu implementieren.

Vielen Danke. Wenn ich noch Probleme habe, meld ich mich nochmals :D

SWE 23. Jun 2008 07:13

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Du solltest natürlich nicht vergessen im Konstruktor Deiner abgeleiteten Klasse "inherited" aufzurufen:

Delphi-Quellcode:
constructor TExtendedObjekt.Create;
begin
  inherited;
  Self.strName := 'Extendet';
end;

Pascal P 23. Jun 2008 07:34

Re: Objekt anhand der Klassenbezeichnung erzeugen
 
Alles seit Freitag in Sack und pack, genau so wie ich es wollte.
Danke nochmals für die gute Hilfe.


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