Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Objekte aus generischem Typ erstellen (https://www.delphipraxis.net/159316-objekte-aus-generischem-typ-erstellen.html)

Neutral General 23. Mär 2011 08:34

Delphi-Version: 2009

Objekte aus generischem Typ erstellen
 
Hallo,

Mir ist leider kein besserer Titel eingefallen.
Es geht darum, dass ich eine "Normale" und eine generische Klasse habe.
Das ganze sieht erstmal so aus:

Delphi-Quellcode:
TKlasseA = class
  constructor Create(AParam: TObject);
end;

TKlasseB<T: TKlasseA> = class
  procedure EineMethode;
end;
Jetzt will ich in TKlasseB<T>.EineMethode() dynamisch ein Objekt vom Typ T erstellen.

Delphi-Quellcode:
procedure TKlasseB<T>.EineMethode;
var X: TObject;
begin
  X := T.Create(Self);
end;
Der Compiler meckert:

Zitat:

[DCC Fehler] Neue Instanz kann ohne CONSTRUCTOR-Einschränkung in der Typparameterdeklaration nicht erstellt werden
Definiere ich KlasseB so:

Delphi-Quellcode:
TKlasseB<T: constructor, TKlasseA> = class
  procedure EineMethode;
end;
Dann kann ich nur den parameterlosen (TObject-)Konstruktor aufrufen:

Delphi-Quellcode:
X := T.Create(Self);
Zitat:

[DCC Fehler] ')' erwartet, aber 'Self' gefunden
Nächster Versuch:

Delphi-Quellcode:
TKlasseA = class
  constructor Create(AParam: TObject);
end;

TKlasseAClass = class of TKlasseA;

TKlasseB<T: TKlasseA> = class
  procedure EineMethode;
end;

procedure TKlasseB<T>.EineMethode;
var Typ: TKlasseAClass;
    X: TObject;
begin
  Typ := TKlasseAClass(T.ClassType);
  X := Typ.Create(Self);
end;
Das kompiliert jetzt zwar, aber ich erhalte beim Aufrufen des Konstruktors eine Zugriffsverletzung.
Ich glaube dass in "Typ" irgendwie keine gültige Klasse drin steht...

Weiß jemand was ich machen kann?

Gruß
Neutral General

webcss 23. Mär 2011 09:27

AW: Objekte aus generischem Typ erstellen
 
Delphi-Quellcode:
procedure TKlasseB<T>.EineMethode;
var X: TObject;
begin
  X := TKlasseA(T).Create(Self);
end;

Neutral General 23. Mär 2011 09:47

AW: Objekte aus generischem Typ erstellen
 
Hallo,

Wenns immer TKlasseA wäre/sein soll, dann wärs ja kein Problem :roll:
Geht ja darum, dass T ja auch jede von TKlasseA abgeleitete Klasse sein kann!

Seltsamerweise funktioniert folgendes:

Delphi-Quellcode:
procedure TKlasseB<T>.EineMethode;
var Typ: TKlasseAClass;
    tmp: T;
    X: TObject;
begin
  tmp := T.Create;
  try
    Typ := TKlasseAClass(tmp.ClassType);
  finally
    tmp.Free;
  end;

  X := Typ.Create(Self);
end;
Das ist jetzt aber keine wirklich schöne/saubere Lösung finde ich.
Also wenn jemand eine Lösung hat in der man kein temporäres Objekt erstellen/freigeben muss, dann
wäre mir das deutlich lieber!

WM_CLOSE 23. Mär 2011 10:23

AW: Objekte aus generischem Typ erstellen
 
Geht es, einen 2. abstrakten Konstruktor zu basteln, also so:
Delphi-Quellcode:
constructor Create2; virtual; abstract;
Den müsste dann jede von KlasseA abgeleitete klasse überschreiben:

Delphi-Quellcode:
constructor TVonKlasseAabgeleitet.Create2();
begin
  TVonKlasseAabgeleitet.Create; //bzw: self.ClassType.Create;??
end;

webcss 23. Mär 2011 11:16

AW: Objekte aus generischem Typ erstellen
 
Delphi-Quellcode:
uses TypInfo;

procedure TKlasseB<T>.EineMethode;
var Typ: TKlasseAClass;
    tmp: T;
begin
  Typ:= TKlasseAClass(T).ClassType;
  tmp:= Typ.Create(self);
end;

himitsu 23. Mär 2011 11:24

AW: Objekte aus generischem Typ erstellen
 
Es gibt bei den Generics leider keine Einschränkungen, wo man etws auf eine bestimmte Klasse (eventuell inklusive Nachfahren) beschränken kann.

Was man maximal sagen kann ist, daß es irgendeine eine Klasse ein soll.

Neutral General 23. Mär 2011 11:38

AW: Objekte aus generischem Typ erstellen
 
Zitat:

Zitat von webcss (Beitrag 1090434)
Delphi-Quellcode:
uses TypInfo;

procedure TKlasseB<T>.EineMethode;
var Typ: TKlasseAClass;
    tmp: T;
begin
  Typ:= TKlasseAClass(T).ClassType;
  tmp:= Typ.Create(self);
end;

Hast du deinen Code mal getestet?^^ Delphi mag das casten von T nicht sonderlich gerne.
:arrow: Es funktioniert so leider nicht.


Zitat:

Zitat von himitsu (Beitrag 1090436)
Es gibt bei den Generics leider keine Einschränkungen, wo man etws auf eine bestimmte Klasse (eventuell inklusive Nachfahren) beschränken kann.

Was man maximal sagen kann ist, daß es irgendeine eine Klasse ein soll.

Nein, man kann tatsächlich folgendes machen:

Delphi-Quellcode:
TGeneric<T: TForm> = class
end;
Und dann meckert der Compiler, wenn man versucht eine TGeneric-Variable mit einem Typ T zu deklarieren, der nicht von TForm erbt. Man kann dann auch eigentlich in Methoden von TGeneric auf die Methoden von TForm zugreifen bei T-Objekten.

Das allgemeine ist:

Delphi-Quellcode:
TGeneric<T: class> = class
end;
Gruß
Neutral General

himitsu 23. Mär 2011 12:28

AW: Objekte aus generischem Typ erstellen
 
Sicher?
Also im 2010er war mir, als wenn es nicht ging, als ich sowas versuchte ... oder war's noch im 2009er :gruebel:

Zitat:

Man kann dann auch eigentlich in Methoden von TGeneric auf die Methoden von TForm zugreifen bei T-Objekten.
Genau das war mein Problem, weil ich sowas wollte und damals ging's nicht.

Neutral General 23. Mär 2011 13:33

AW: Objekte aus generischem Typ erstellen
 
Doch das geht.
Das geht/ging von Anfang an. Ich benutze das hier mit Delphi 2009 ;)

Edit: Ok, auf das Objekt zugreifen (T.Caption := 'Test123') funktioniert nicht:

Zitat:

[DCC Fataler Fehler] Unit1.pas(30): F2084 Interner Fehler: AV052BF081-R00000000-0
Mh. Nagut.
Wies mit Delphi2010/XE ist kann ich momentan nicht sagen weil ich hier grad nur Delphi 2009 hab.


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