Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];

Вниз

Как создать объект по имени его класса   Найти похожие ветки 

 
Чайник ©   (2004-12-15 18:43) [0]

У меня создан базовый класс типа TBlock = class(TComponent), и ряд производных от него классов вида TBlock1 = class(TBlock), TBlock2 и т.д. Как в программе создать объект конкретного класса, если я знаю его имя (имя сидит в строке вроде NewBlock = "TBlock1" : string)?


 
Суслик ©   (2004-12-15 18:47) [1]

изучай registerclass + findclass


 
Чайник ©   (2004-12-15 18:57) [2]

Изучаю.
Каждый модуль с описанием класса имеет секцию

 initialization
   RegisterClass(TBlock1);

Далее, в программе объявлен тип:

  type TBlockClass = class of TBlock;

В процедуре добавления блока есть

  var tmpBlockClass : TBlockClass;
  tmpBlock : TBlock;
  ...

  tmpBlockClass := TBlockClass(FindClass(newBlock));
  tmpBlock := tmpBlockClass.Create(Self);

При запуске имею: Class TBlock1 not found. Почему?


 
jack128 ©   (2004-12-15 19:11) [3]

а чему равно newBlock на момент вызова??
Когда вызывается процедура добавления? Случайно не в секции ининциализации?
а если так  tmpBlockClass := TBlockClass(FindClass("TBlock1")); то работает??


 
Чайник ©   (2004-12-15 19:17) [4]

>а чему равно newBlock на момент вызова??
newBlock содержит имя класса;
>Когда вызывается процедура добавления? Случайно не в секции ининциализации?  - нет, из процедуры.
>а если так  tmpBlockClass := TBlockClass(FindClass("TBlock1")); то работает??
нет, и так не работает.


 
jack128 ©   (2004-12-15 19:20) [5]

хм. Больше мыслкй нет.  Отладчиком пройдись, что еще можно посоветовать...


 
Чайник ©   (2004-12-15 19:34) [6]

Опа!
У меня секция initialization не выполняется! Что за новости???


 
Sergey_Masloff   (2004-12-15 19:53) [7]

Чайник ©   (15.12.04 19:34) [6]
>У меня секция initialization не выполняется! Что за новости???
Значит этого модуля в USES нигде нет. Проверь?


 
Чайник ©   (2004-12-15 20:31) [8]

Вы будете смеяться, но теперь не выполняется секция finalization.
Чтобы это значило?
Кстати, а она всегда должна выполняться?


 
Sergey_Masloff   (2004-12-15 20:46) [9]

Вобщем, ничего не понятно. Тебе нужно что-то типа этого?

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   btCreate: TButton;
   btClose: TButton;
   procedure btCloseClick(Sender: TObject);
   procedure btCreateClick(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation
uses Unit2;

{$R *.dfm}

procedure TForm1.btCloseClick(Sender: TObject);
begin
 Close();
end;

procedure TForm1.btCreateClick(Sender: TObject);
var
 cls : TComponentClass;
 ptr : Pointer;
begin
 cls := TComponentClass(GetClass(Edit1.Text));
 if Assigned(cls) then
 try
   ptr := cls.Create(Application);
   ShowMessage(TBlock1(ptr).GetName);
 finally
   TObject(ptr).Free();
 end else
   ShowMessage("Класс не найден");end;

end.

//////// Unit2
unit Unit2;

interface
uses Classes;

type
 TBlock = class(TComponent);

 TBlock1 = class(TBlock)
 public
   function GetName : String;
 end;

implementation

{ TBlock1 }

function TBlock1.GetName: String;
begin
 Result := "TBlok1 at your service!";
end;

initialization
 RegisterClass(TBlock1);

end.


Форма с 2 кнопками и едитом. В едит вводишь TBlock1 получаешь строку возвращаемую TBlock1.GetName. Тебе это нужно


 
Чайник ©   (2004-12-15 22:27) [10]

Прошу прощения, вынужденно отвлекся от занимательной дискуссии.

>Sergey_Masloff
У меня объявлен массив Blocks : array of TBlock; , так вот, мне нужно, чтобы вызывался конструктор Create именно конкретного производного класса (TBlock1 или TBlock2 или TBlockN), а не родительского TBlock.

Я пробовал по Вашему совету:

procedure TFEditor.btnBlockAddClick(Sender: TObject);
var tmpBlockClass : TComponentClass;
   tmpBlock : Pointer;

...

    tmpBlockClass := TComponentClass(GetClass(newBlock));
    tmpBlock := tmpBlockClass.Create(Self);



Выполняется Create родительского класса, а не того, чье имя сидит в newBlock


 
Чайник ©   (2004-12-15 22:36) [11]

Ответ на собственный вопрос:
>Вы будете смеяться, но теперь не выполняется секция finalization.
>Чтобы это значило?
>Кстати, а она всегда должна выполняться?

У меня для отладки туда воткнуто ShowMessage("finalization");

Так вот ShowMessage отображается, только тотчас исчезает.


 
vuk ©   (2004-12-15 22:46) [12]

to Чайник ©   (15.12.04 22:27) [10]:
>так вот, мне нужно, чтобы вызывался конструктор Create именно
>конкретного производного класса (TBlock1 или TBlock2 или
>TBlockN), а не родительского TBlock.
Конструктор сделайте виртуальным. Как, например, это у TComponent сделано.


 
Sergey_Masloff   (2004-12-15 22:48) [13]

Перепишем Unit2

unit Unit2;

interface
uses Classes;

type
TBlock = class(TComponent)
protected
  fData : String;
public
  function GetName : String;
end;

TBlock1 = class(TBlock)
public
  constructor Create(AOwner : TComponent); reintroduce; override;
end;

TBlock2 = class(TBlock)
public
  constructor Create(AOwner : TComponent); reintroduce; override;
end;

implementation

{ TBlock1 }

{ TBlock }

function TBlock.GetName: String;
begin
 result := fData;
end;

{ TBlock1 }

constructor TBlock1.Create(AOwner: TComponent);
begin
 inherited;
 fData := "Block1 at service";
end;

{ TBlock2 }

constructor TBlock2.Create(AOwner: TComponent);
begin
 inherited;
 fData := "Block2 at service";
end;

initialization
RegisterClasses([TBlock1, TBlock2]);

end.


При вводе имен разных блоков выдаются разные сообщения - т.е. конструкторы работают. Там нигде override не забыли в иерархии?


 
Zacho ©   (2004-12-15 22:48) [14]

Чайник ©   (15.12.04 22:27) [10]

Приведи свой код полностью. А то есть у меня некоторые подозрения, да телепатировать лень :)


 
Sergey_Masloff   (2004-12-15 22:50) [15]

vuk ©   (15.12.04 22:46) [12]
>Конструктор сделайте виртуальным. Как, например, это у >TComponent сделано.
Это все потомки TComponent наверное где-то виртуальный конструктор заместили статическим. Вобщем код надо смотреть подробнее.


 
Чайник ©   (2004-12-15 22:51) [16]

Ура! Заработало! (с) Матроскин.

Работающий вариант:


procedure TFEditor.btnBlockAddClick(Sender: TObject);
var tmpBlockClass : TBlockClass;
   tmpBlockClassName : String;

...

    tmpBlockClassName := ListNamesBlock[tmpNo].ClassName;

    tmpBlockClass := TBlockClass(FindClass(tmpBlockClassName));

    BlocksCount := BlocksCount + 1;
    SetLength(Blocks, BlocksCount);
    Blocks[BlocksCount-1] := tmpBlockClass.Create(Self);
    Blocks[BlocksCount-1].Caption := и т.д.



 
vuk ©   (2004-12-15 22:53) [17]

to Sergey_Masloff   (15.12.04 22:50) [15]:
>Это все потомки TComponent наверное где-то виртуальный
>конструктор заместили статическим.
Ну тогда просто override дописать. Сути это не меняет. Либо виртуальный конструктор отсутствует либо определен новый с другой сигнатурой. Другим путем такого эффекта не добиться. А что там на самом деле происходит - фиг его знает. Кода нет, а телепаты в отпуске.


 
Чайник ©   (2004-12-15 22:53) [18]

Кстати, а оно обязательно надо:

finalization

 UnRegisterClass(TBlockCylinder2Dsimm);


 
Sergey_Masloff   (2004-12-15 22:59) [19]

Чайник ©   (15.12.04 22:53) [18]
>Кстати, а оно обязательно надо:
>finalization
> UnRegisterClass(TBlockCylinder2Dsimm);
Не надо. Это можно сделать в коде программы для высвобождения ресурсов но не в финализации - все равно все высвободится автоматически.


 
Чайник ©   (2004-12-15 23:09) [20]

> Sergey_Masloff   (15.12.04 22:59) [19]

Спасибо



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.01.02;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.036 c
1-1103298655
saNat
2004-12-17 18:50
2005.01.02
Курсор в TMemo


1-1103122513
Erik1
2004-12-15 17:55
2005.01.02
Как получить свойство ReadOnly в неизвестном наследнике?


1-1103283641
V l a d i m i r
2004-12-17 14:40
2005.01.02
Обработка клавиш YESNOCANCEL в MessageBox


3-1101986159
Chery
2004-12-02 14:15
2005.01.02
Стринг - Дата - Максимальное значение.


3-1102318362
Mid
2004-12-06 10:32
2005.01.02
проблема с таблицами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский