Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> массив классов, не объектов, а именно классов! 
V
    Опции темы
shmelina
Дата 19.6.2009, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



У меня есть базовый класс. От него есть наследники.
В записимости от параметра конструктора мне нужно создавать или базовый класс или кого-то из его наследников. Я сделал отдельную процедуру для этого:

Код

function CreateWinTbl(ATbl: TTbl): TWinTbl;
begin
  if ATbl.Table = 'OBJ' then
    Result := TWinTblObj.Create(ATbl)
  else
  if ATbl.Table = 'FLD' then
    Result := TWinTblFld.Create(ATbl)
  else
    Result := TWinTbl.Create(ATbl);
end;


Сейчас пока всего два унаследованных класса, но их будет много. Мне не очень нравится многоэтажная конструкция IF. Есть ли способ попроще?

Мне бы хотелось какой-нить константный массив сделать. А в этой процедуре пробегать по маассиву и создавать нужный класс. 

Нечто подобное я делал, но с рекордами:
Код

type
  TFldTypeTableRec = record // Тип поля
    ID: Integer;
    Name: string;
    FldType: TFldType;
  end;

var
  // Типы полей
  FldTypeTable: array [0..4] of TFldTypeTableRec = (
    (ID: 0; Name: 'integer';  FldType: ftInteger),
    (ID: 0; Name: 'string';   FldType: ftString),
    (ID: 0; Name: 'boolean';  FldType: ftBoolean),
    (ID: 0; Name: 'float';    FldType: ftFloat),
    (ID: 0; Name: 'datetime'; FldType: ftDateTime)
  );


Есть идеи?
PM MAIL   Вверх
Frees
Дата 19.6.2009, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



вот как то так 
Код

obj: TObject;  //родительский класс
cl: array [0..1] of TClass = (TStringList, TObject);//потомки

procedure TForm21.Button1Click(Sender: TObject);
begin
  obj := cl[0].Create;//создаем нужный потомок
  TStringList(obj).Add('fff');
  caption := TStringList(obj).Text
  obj.Free;
end;


Это сообщение отредактировал(а) Frees - 19.6.2009, 14:53


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Rennigth
Дата 19.6.2009, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76



Зачем вообще эти извращения? передавай в коструктор класс твоего объекта. Класс обявляется так:

Код

TSomeObject = class
//...
end;
TSomeObjectClass = class of TSomeObject;

Для всех твоих классов объяви, и передавай нужный. Будет что-то вроде:
Код

function CreateWinTbl(ASomeObjectClass: TSomeObjectClass; ATbl: TTbl): TWinTbl;
begin
    Result := ASomeObjectClass.Create(ATbl);
end;





--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
shmelina
Дата 24.6.2009, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Frees @ 19.6.2009,  14:50)
вот как то так 
Код

obj: TObject;  //родительский класс
cl: array [0..1] of TClass = (TStringList, TObject);//потомки

procedure TForm21.Button1Click(Sender: TObject);
begin
  obj := cl[0].Create;//создаем нужный потомок
  TStringList(obj).Add('fff');
  caption := TStringList(obj).Text
  obj.Free;
end;

Не получается с классами, у которых в конструкторе есть параметры.
PM MAIL   Вверх
shmelina
Дата 24.6.2009, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Rennigth @ 19.6.2009,  16:06)
Зачем вообще эти извращения? передавай в коструктор класс твоего объекта. Класс обявляется так:

Код

TSomeObject = class
//...
end;
TSomeObjectClass = class of TSomeObject;

Для всех твоих классов объяви, и передавай нужный. Будет что-то вроде:
Код

function CreateWinTbl(ASomeObjectClass: TSomeObjectClass; ATbl: TTbl): TWinTbl;
begin
    Result := ASomeObjectClass.Create(ATbl);
end;

В том то и проблема, что мне нужно определить какой класс создавать.
Определение получается многоэтажным IF-ом. Этого и хочется избежать и сделать все как-то через массив.

Еще раз опишу задачу.

1. Есть некий класс, обладающий стандартной функциональностью.
2. Есть наследники, обладающие измененной функциональностью.
3. Какой именно класс создавать отпределяется неким параметром. Этот параметр передается в конструктор класса (но это не важно).
4. Смущает многоэтажный IF, который я использую для определения того, какой класс создавать.
Код

function CreateWinTbl(ATbl: TTbl): TWinTbl;
begin
  if ATbl.Table = 'OBJ' then
    Result := TWinTblObj.Create(ATbl) // Объект
  else
  if ATbl.Table = 'FLD' then
    Result := TWinTblFld.Create(ATbl) // Поле
  else
  if ATbl.Table = 'TBL' then
    Result := TWinTblTBL.Create(ATbl) // Таблица
  else
  if ATbl.Table = 'CARD' then
    Result := TWinTblCard.Create(ATbl) // Карточка
  else
    Result := TWinTbl.Create(ATbl); // Стандартный класс
end;

5. Хочется сделать все как-то через массив. Т.е. пусть в массиве содержится список классов (или конструкторов?) и условий для них. Так это смотрится гораздо изящнее. Ну например так:
Код

type
  TWinTblClass = record
    Table: string;
    ClassName: TClass;
  end;
var
  WinTblClassArray: array [0..3] of TWinTblClass = (
  (Table: 'OBJ'; ClassName: TWinTblObj),
  (Table: 'FLD'; ClassName: TWinTblFld),
  (Table: 'TBL'; ClassName: TWinTblTbl),
  (Table: 'CARD'; ClassName: TWinTblCard)
  );

А процедура для создания класса  - примерно так:
Код

function CreateWinTbl(ATbl: TTbl): TWinTbl;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to Length(WinTblClassArray) - 1 do
    if WinTblClassArray[I].Table = ATbl.Obj.Table then
    begin
      Result := WinTblClassArray[I].ClassName.Create(ATbl); // Это конечно не работает :(
      Break;
    end;
  if not Assigned(Result) then
    Result := TWinTbl.Create(ATbl);
end;


Это сообщение отредактировал(а) shmelina - 25.6.2009, 09:31
PM MAIL   Вверх
cemick
Дата 25.6.2009, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Код

unit Unit1;

interface

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

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

 TMyBaseClass = class(TObject)
 public
    constructor Create(AParams: array of const); virtual;
 end;

 TMyBaseClassRef = class of TMyBaseClass;

 TMyClass1 = class(TMyBaseClass)
 public
 end;

 TMyClass2 = class(TMyBaseClass)
 public
 end;

 TMyClass3 = class(TMyBaseClass)
 public
 end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
   List: TList;
begin
    List := TList.Create;
    List.Add(TMyClass1);
    List.Add(TMyClass2);
    List.Add(TMyClass3);

    for I := 0 to List.Count - 1 do
      Obj := TMyBaseClassRef(List.Items[i]).Create([]);
    ShowMessage(Obj.ClassName);
end;

{ TTMyBaseClass }

constructor TMyBaseClass.Create(AParams: array of const);
begin
  inherited Create;
end;

end.



Это сообщение отредактировал(а) cemick - 25.6.2009, 19:18
PM MAIL WWW   Вверх
shmelina
Дата 26.6.2009, 10:04 (ссылка)   | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(cemick @ 25.6.2009,  19:17)
Код

unit Unit1;

interface

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

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

 TMyBaseClass = class(TObject)
 public
    constructor Create(AParams: array of const); virtual;
 end;

 TMyBaseClassRef = class of TMyBaseClass;

 TMyClass1 = class(TMyBaseClass)
 public
 end;

 TMyClass2 = class(TMyBaseClass)
 public
 end;

 TMyClass3 = class(TMyBaseClass)
 public
 end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
   List: TList;
begin
    List := TList.Create;
    List.Add(TMyClass1);
    List.Add(TMyClass2);
    List.Add(TMyClass3);

    for I := 0 to List.Count - 1 do
      Obj := TMyBaseClassRef(List.Items[i]).Create([]);
    ShowMessage(Obj.ClassName);
end;

{ TTMyBaseClass }

constructor TMyBaseClass.Create(AParams: array of const);
begin
  inherited Create;
end;

end.


Не совсем понял, что ты хотел сказать, но:
1. Мне не нужно объекты сразу создавать. Одна из причин - может быть создано несколько объектов одного класса.
2. Ты не решил проблему выбора какой именно объект создавать. Опять многоэтажный IF?
PM MAIL   Вверх
cemick
Дата 26.6.2009, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(shmelina @  26.6.2009,  10:04 Найти цитируемый пост)
Не совсем понял, что ты хотел сказать, но:
1. Мне не нужно объекты сразу создавать. Одна из причин - может быть создано несколько объектов одного класса.
2. Ты не решил проблему выбора какой именно объект создавать. Опять многоэтажный IF?

Тебе нужно было хранить классы в массиве, а потом динамически, на основе индекса например, создать объекты, я тебе показал как хранить класс в массиве можно и как создать объект, я не писал код за тебя.
Ты же сам хотел что то наподобии:

Код

function CreateWinTbl(ATbl: TTbl): TWinTbl;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to Length(WinTblClassArray) - 1 do
    if WinTblClassArray[I].Table = ATbl.Obj.Table then
    begin
      Result := WinTblClassArray[I].ClassName.Create(ATbl); // Это конечно не работает :(
      Break;
    end;
  if not Assigned(Result) then
    Result := TWinTbl.Create(ATbl);
end;



Это сообщение отредактировал(а) cemick - 26.6.2009, 12:03
PM MAIL WWW   Вверх
jsa
Дата 26.6.2009, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 704
Регистрация: 19.1.2006
Где: Новосибирск

Репутация: 1
Всего: 20



shmelina, смотри в сторону RegisterClass, FindClass и будет тебе счастье
разом и от массивов избавишься и от if'ов

Добавлено через 9 минут и 56 секунд
только учти, что базовый класс должен наследоваться от как минимум от  TPersistent


--------------------
Все мы, на перине с песней, строим небо на земле © Ю. Шевчук
PM MAIL ICQ   Вверх
shmelina
Дата 29.6.2009, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(Frees)
вот как то так

У меня скомпилировать не получалось это:
Код

Result := WinTblClassArray[I].ClassName.Create(ATbl);

Сейчас сообразил сделать так:
Код

Result := TWinTbl(WinTblClassArray[I].ClassName).Create(ATbl);

Но при попытке создать объект получаю AV. Ошибка в этом месте:
Код

constructor TWinTbl.Create(AOwner: TComponent; AParent: TWinControl; ATbl: TTbl);
begin
  inherited Create;
  Owner := AOwner; // Здесь ошибка AV
  Parent := AParent;

Такое ощущение, что я не правильно создаю класс. Спотыкается на простейшей операции присваивания!
Не смотрите, что количество параметров в конструкторе вдруг другое. Я просто перед этим упрощал для вас.

Это сообщение отредактировал(а) shmelina - 29.6.2009, 12:27
PM MAIL   Вверх
cemick
Дата 29.6.2009, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 416
Регистрация: 6.7.2006
Где: Санкт-Петербург

Репутация: 2
Всего: 6



Цитата(shmelina @  29.6.2009,  12:08 Найти цитируемый пост)
Такое ощущение, что я не правильно создаю класс. Спотыкается на простейшей операции присваивания!
Не смотрите, что количество параметров в конструкторе вдруг другое. Я просто перед этим упрощал для вас.

свойство Owner read only.  Передавай его inherited create (AOwner);


Это сообщение отредактировал(а) cemick - 29.6.2009, 12:38
PM MAIL WWW   Вверх
shmelina
Дата 29.6.2009, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(cemick @ 29.6.2009,  12:37)
свойство Owner read only.  Передавай его inherited create (AOwner);

Это мое свойство. Оно не ReadOnly.
Думаю если бы оно было ReadOnly, то ошибка была бы не AV, а что-то другое.
С многоэтажным IF-ом все работает. А как только я переделываю на массив с циклом - ошибка.
PM MAIL   Вверх
Frees
Дата 29.6.2009, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



может у тебя конструктор потомка не вызывается, а только конструктор родителя?

объяви как то так конструкторы попробуй

Код

  TMyBaseClass = class (TMyBaseBaseClass)
  public
    Text: string;
    constructor Create(str: string);virtual;
  end;

  TMyClass1 = class(TMyBaseClass)
  public
    constructor Create(str: string);override;
  end;



--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
shmelina
Дата 29.6.2009, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



У потомков нет констуруктора. Только некоторые функции переопределены.
PM MAIL   Вверх
Frees
Дата 29.6.2009, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 9
Всего: 54



Цитата(shmelina @  29.6.2009,  15:08 Найти цитируемый пост)
Result := TWinTbl(WinTblClassArray[I].ClassName).Create(ATbl);


ерунда полная!!!

ClassName - это строка а не ссылка на класс!!!

Добавлено @ 12:56
пардон не то посмотрел

для начала
Код

Result := TWinTbl(WinTblClassArray[I].ClassName.Create(ATbl));

и еще
Код

type
    TMyClass = class of TWinTbl;
TWinTblClass = record
    Table: string;
    ClassName: TMyClass;
  end;
var
  WinTblClassArray: array [0..3] of TWinTblClass = (
  (Table: 'OBJ'; ClassName: TWinTblObj),
  (Table: 'FLD'; ClassName: TWinTblFld),
  (Table: 'TBL'; ClassName: TWinTblTbl),
  (Table: 'CARD'; ClassName: TWinTblCard)
  );


паардон если чет не понял запутался я в этом топике

Это сообщение отредактировал(а) Frees - 29.6.2009, 12:59


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.