Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Динамическое создание классов [D4, NT4]


Давид ©   (2002-07-11 16:42:00) 

Хотелось бы узнать, существует ли способ динамически создать объект определенного класса в Дельфи. Представьте себе, что в есть список пользовательских классов (Class1, Class2, ...) и, в зависимости от выбора, программа создает объект выбранного класса. Заранее благодарю за все предложения по данной проблеме.

Давид


psvital   (2002-07-11 21:11:00) [1]

> Давид
Лови пример, он работает.


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

type
TmyBasic = class(TPersistent)
public
constructor Create; virtual;
function GetName :string; virtual;
end;

TMyClass = class(TmyBasic)
public
constructor Create; override;
function GetName :string; override;
end;


procedure TForm1.Button1Click(Sender: TObject);
var Instance :TPersistentClass;
Obj :TMyBasic;
begin
Instance := GetClass("TMyClass");
Obj := TMyBasic(Instance.NewInstance);
MessageBox(Handle, PChar(obj.GetName), "Test", MB_OK);
Obj.Free;
end;

{ TmyBasic }

constructor TmyBasic.Create;
begin
//
end;

function TmyBasic.GetName: string;
begin
Result := "TmyBasic";
end;

{ TMyClass }

constructor TMyClass.Create;
begin
inherited;
//
end;

function TMyClass.GetName: string;
begin
Result := "TMyClass";
end;

initialization
RegisterClasses([TMyBasic, TMyClass]);

end.


Давид   (2002-07-11 20:55:00) [2]

Все, нашел в чем собака зарыта. Если кому-то еще интересно, вот исправленный код

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TClassRef = class of TBasisClass;

TBasisClass = class (TPersistent)
constructor Create(); virtual;
public
Name: String;
end;

TChildClass = class(TBasisClass)
constructor Create(); override;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

constructor TBasisClass.Create();
begin
inherited Create();
end;

constructor TChildClass.Create();
begin
Name := "David";
inherited Create();
end;

procedure TForm1.Button1Click(Sender: TObject);
var
MyObj: TObject;
begin
MyObj := TClassRef(GetClass("TChildClass")).Create;
ShowMessage((MyObj as TBasisClass).Name);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TBasisClass, TChildClass]);
end;

end.

Всем огромное спасибо. Тема закрыта.

Давид


Давид   (2002-07-11 20:35:00) [3]

> reonid

Я попробовал с виртуальным конструктором маленький тест. Но что-то не так. Вот код

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type

TBasisClass = class(TPersistent)
constructor Create(); virtual;
public
Name: String;
end;

TChildClass = class(TBasisClass)
constructor Create(); override;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

constructor TBasisClass.Create();
begin
inherited Create();
end;

constructor TChildClass.Create();
begin
Name := "David";
inherited Create();
end;

procedure TForm1.Button1Click(Sender: TObject);
var
MyObj: TObject;
begin
// Здесь во время выполнения получаю ошибку
MyObj := TBasisClass(GetClass("TChildClass")).Create;
ShowMessage((MyObj as TBasisClass).Name);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TBasisClass, TChildClass]);
end;

end.


Skier   (2002-07-11 19:07:00) [4]

>Давид

> а параметры aParam1, aParam2 подгружаются динамически из
> include-файлов во время компиляции.


??? Я в замешательстве :)


Давид   (2002-07-11 19:02:00) [5]

> reonid

С виртуальным конструктором, к сожалению, не получается из-за различия в описании конструкторов. Даю описание классов:

TFormat = class (TPersistent)
constructor Create(aParam1, aParam2: String);

TClass1 = class (TFormat)
constructor Create();

В конструкторе класса TClass1 вызывается конструктор родительского класса: inherited Create(aParam1, aParam2), а параметры aParam1, aParam2 подгружаются динамически из include-файлов во время компиляции.


Skier   (2002-07-11 18:32:00) [6]

>reonid
А как объявлен TFormat - посмотри.


MBo   (2002-07-11 18:31:00) [7]

procedure TForm1.Button1Click(Sender: TObject);
type
TWCClass = class of TWinControl;
var
Obj:TWinControl;
ObjClass:TWCClass;
begin
RegisterClass(TButton);
RegisterClass(TEdit);
ObjClass:=TWCClass(GetClass(edit1.text));
if ObjClass<>nil then begin
Obj:=ObjClass.Create(self);
Obj.Parent:=self;
Obj.SetBounds(10,10,100,20);
end;
end;


reonid   (2002-07-11 18:30:00) [8]

Всё правильно у него ругается.
GetClass.Create возвращает TPersistent, а у него TFormat.

А с виртуальным конструктором
TFormat(GetClass("Class2")).Create;
будет правильно работать


Skier   (2002-07-11 18:26:00) [9]

>Давид
Ты уж его и так засорил.
Давай высылай...


Skier   (2002-07-11 18:25:00) [10]

>reonid
Да какой, виртуальным ! Он, блин, говорит, что у
него Delphi ругается на строку MyClass := GetClass("Class2").
Какие уж тут конструкторы.

В общем - всё запушено...:(


Давид   (2002-07-11 18:23:00) [11]

> Skier

Могу отправить по e-mail (kozhanov@newmail.ru)? Не хочу засорять форум.

Давид


reonid   (2002-07-11 18:23:00) [12]

2 Давид
сделай конструктор виртуальным


Skier   (2002-07-11 18:15:00) [13]

>Давид
Давай код полностью. Как ты всё это делаешь.


Давид   (2002-07-11 18:13:00) [14]

> Skier

Так плохо. В строке MyClass := GetClass("Class2")Дельфи дает ошибку. Надо писать MyClass := TFormat(GetClass("Class2")), но тогда MyObj := MyClass.Createвызывает Create класса TFormat, а не Class2.

Давид


Skier   (2002-07-11 17:45:00) [15]

>Давид



MyClass: TFormat;
MsgObj: TPersistent;

.......................

MyClass := GetClass("Class2");
if MyClass <> nil then MyObj := MyClass.Create;


Давид   (2002-07-11 17:41:00) [16]

> Skier

Вся проблема в строке MsgObj: Class2. Я не хочу описывать переменные всех классов. Вместо этого, хотелось бы создать переменную общего типа и потом изменить тип. В таком случае получилась бы программа, не зависящая от добавления новых классов.

Давид


Skier   (2002-07-11 17:34:00) [17]

>Давид


MyClass: TFormat;
MsgObj: Class2;

.......................

MyClass := GetClass("Class2");
if MyClass <> nil then MyObj := MyClass.Create;


Давид   (2002-07-11 17:31:00) [18]

> Skier

Честно говоря, получается не так как хотелось бы. У меня есть классы Class1, Class2, ..., которые имеют общего предка - класс TFormat = class of TPersistent. Пользователь выбирает, на пример, "Class2". В программе я регистрирую классы Class1, Class2, ... и описываю переменные

MyClass: TClass;
MsgObj: TObject;

Затем делаю

MyClass := GetClass("Class2");
MyObj := MyClass.Create;

Логично было бы, если бы вызывался метод Create класса Class2, но вызывается TFormat.Create.


Skier   (2002-07-11 16:48:00) [19]

>Давид
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1026125231&n=0


Наверх

Титульная страница Поиск, карта сайта Написать письмо