Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как передать тип? / 25 сообщений из 25, страница 1 из 1
23.09.2003, 14:37
    #32273018
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Есть набор классов, наследников базового.
Надо сделать класс-массив их (один на всех). В одном экземпляре массива должны находиться экземпляры только одного из классов.
Как в конструктор передать тип класса наследника и отслеживать вызов методов (например, Add) с экземпляром другого класса в качестве параметра?
...
Рейтинг: 0 / 0
23.09.2003, 14:47
    #32273031
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
т.е. как я понял у класса-массива будет опция которая определеяет для какого типа создан данный экземпляр? ... ну например так:

type
TB = class
..........
end;

TD1 = class
..........
end;
TD2 = class
..........
end;

TArrayB = class
TypeOption : (toD1, toD2);
procedure Add(const B : TB);
end;

procedure TArrayB.Add(const B : TB);
begin
case TypeOption of
toD1 : if B is TD1 then ... else ...;
toD2 : if B is TD2 then ... else ...;
end;
.....
end;
...
Рейтинг: 0 / 0
23.09.2003, 14:51
    #32273039
Малиновский Владимир
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
type
TBaseClass = class(TObject)
...
end;

TMyClass1 = class(TBaseClass)
...
end;

TMyClass2 = class(TBaseClass)
...
end;

TMyClasses = class of TBaseClass;
//-------------------------------

var
arr_class = array [1..2] of TMyClasses;

//----

begin

arr_class := TMyClass1.Create;
arr_class := TMyClass2.Create;
//---------------------------
// Или я тебя не понял?
// Че делаем - то?

end
...
Рейтинг: 0 / 0
23.09.2003, 15:09
    #32273086
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Малиновский Владимир,
Что это !?
...
Рейтинг: 0 / 0
23.09.2003, 15:16
    #32273109
Малиновский Владимир
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Вот и я о том же
...
Рейтинг: 0 / 0
23.09.2003, 15:21
    #32273126
Малиновский Владимир
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
arr_class := TMyClass1.Create;
arr_class := TMyClass2.Create;
...
Рейтинг: 0 / 0
23.09.2003, 15:24
    #32273134
Малиновский Владимир
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Что-то у меня квадратные скобки с индексами массива не выводятсся в опубликованную ерунду... Только шрифт меняется...
...
Рейтинг: 0 / 0
23.09.2003, 16:13
    #32273253
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Потому, что они в тэги преобразовываются - вот и не выводятся. Наверное где-то на форуме написано, чё с ними делать, если показать надо.
...
Рейтинг: 0 / 0
24.09.2003, 07:32
    #32273582
Mik Prokoshin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Делается массив для базового класса. Все наследуемые могут в нем спокойно содержаться. Естественно, что оперировать без явных преобразований можно только методами базового класса (с учетом virtual). А то, что Вы пытаетесь сделать попахивает мультиметодами (методами, применимыми к разным классам). Не советую :-)
...
Рейтинг: 0 / 0
24.09.2003, 09:22
    #32273661
zDIV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Да, для базового...
ну а массив объект можно очень просто реализовать на основе TCollection или на TObjectList, в простейшем варианте типа

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
  TTaskFormList = class(TObjectList)
  private
    { Private declarations }
    function GetItem(Index: Integer): TTaskForm;
    procedure SetItem(Index: Integer; Value: TTaskForm);
  protected
    { Protected declarations }
  public
    { Public declarations }
    property Items[Index: Integer]: TTaskForm read GetItem write SetItem; default;
  end;

function TTaskFormList.GetItem(Index: Integer): TTaskForm;
begin
  Result := TTaskForm(inherited GetItem(Index));
end;

procedure TTaskFormList.SetItem(Index: Integer; Value: TTaskForm);
begin
  inherited SetItem(Index, Value);
end;



и все готово...
...
Рейтинг: 0 / 0
24.09.2003, 11:46
    #32273851
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Возможно я не совсем корректно сформулировал мысль.
Есть базовый класс, есть его наследники с интерфейсом базового класса, есть класс - набор наследников (на основе TList). В одном экземпляре класса-набора могут содержаться дофига элементов, но все - одного класса-наследника. Ситуация когда в наборе содержатся различные наследники недопустима. Чтобы не создавать кучу потомков набора (для каждого наследника свой) есть такая "идея":
При создании экземпляра класса-набора в параметре constructor-а предается тип содержания. Например так: MyList:=TMyList.Create(TMyType1);
Все добавляемые в набор классы костятся к TMyType1.
Т.к. прикостить наследника можно только к родителю, а не к "брату" (или я ошибаюсь?), то попытка добавления в набор "брата" приведет к ошибке, чего я и добиваюсь. Вопрос: Как передать тип в Create, а затем использовать его для приведения? Т.е. чего писать в constructor Create(A:????)
и как потом приводить List ^ к типу А.
На данный момент я все привожу к базовому классу, что позволяет создавать "смешенные наборы", а это не допустимо.
...
Рейтинг: 0 / 0
24.09.2003, 12:44
    #32273943
m_kus
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Класс передать можно так:
Код: plaintext
1.
2.
3.
4.
type TItemClass=class of TItem;
...
type TMyList=class(TList);
  constructor Create(A:TItemClass);

Что насчёт того, как приводить, то не знаю, сам разбирайся...
...
Рейтинг: 0 / 0
24.09.2003, 13:03
    #32273991
zDIV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
TObjectList намного круче TList, поскольку самостоятельно контролирует (если это нужно, AOwnsObjects = True) уничтожение объектов своего списка!

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
  TTaskForm = class(TObject)
  ...
  TAaaTaskForm = class(TTaskForm)
  ...
  TBbbTaskForm = class(TTaskForm)
  ...

  TTaskFormList = class(TObjectList)
  private
    { Private declarations }
    FTaskFormClass: TTaskFormClass;
    function CheckObject(AObject: TObject): Boolean;
    function GetItem(Index: Integer): TTaskForm;
    procedure SetItem(Index: Integer; Value: TTaskForm);
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(ATaskFormClass: TTaskFormClass); overload;
    constructor Create(AOwnsObjects: Boolean; ATaskFormClass: TTaskFormClass); overload;
    function Add(AObject: TTaskForm): Integer;
    procedure Insert(Index: Integer; AObject: TTaskForm);
    property Items[Index: Integer]: TTaskForm read GetItem write SetItem; default;
  end;

function TTaskFormList.CheckObject(AObject: TObject): Boolean;
begin
  Result := Assigned(AObject) and (AObject is FTaskFormClass);
end;

function TTaskFormList.GetItem(Index: Integer): TTaskForm;
begin
  Result := TTaskForm(inherited GetItem(Index));
end;

procedure TTaskFormList.SetItem(Index: Integer; Value: TTaskForm);
begin
  if not CheckObject(Value) then Exit;
  if IndexOf(Value) <> - 1  then Exit;
  inherited SetItem(Index, Value);
end;

constructor TTaskFormList.Create(ATaskFormClass: TTaskFormClass);
begin
  inherited Create;
  FTaskFormClass := ATaskFormClass;
end;

constructor TTaskFormList.Create(AOwnsObjects: Boolean; ATaskFormClass: TTaskFormClass);
begin
  inherited Create(AOwnsObjects);
  FTaskFormClass := ATaskFormClass;
end;

function TTaskFormList.Add(AObject: TTaskForm): Integer;
begin
  if not CheckObject(AObject) then begin Result := - 1 ; Exit; end;
  Result := IndexOf(AObject); if Result <> - 1  then Exit;
  Result := inherited Add(AObject);
end;

procedure TTaskFormList.Insert(Index: Integer; AObject: TTaskForm);
begin
  if not CheckObject(AObject) then Exit;
  if IndexOf(AObject) <> - 1  then Exit;
  inherited Insert(Index, AObject);
end;

...
Рейтинг: 0 / 0
24.09.2003, 13:18
    #32274027
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
TTaskFormClass ?????????
...
Рейтинг: 0 / 0
24.09.2003, 14:16
    #32274146
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Откомпилировано и проверено:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
program Classes;
uses
  SysUtils, Dialogs;

type
   TBaseClass = class
   end;

   TClass1 = class(TBaseClass)
   end;
   TClass2 = class(TBaseClass)
   end;
   TClass3 = class(TBaseClass)
   end;
   // i t.d ....
   TBaseClassClass = class of TBaseClass;
   TArrayOfClasses = class
   private
      ListClassName : string;
      Items : array of TBaseClass;
   public
      procedure Add(const bo : TBaseClass);
      constructor Create(C : TBaseClassClass);
   end;

procedure TArrayOfClasses.Add(const bo: TBaseClass);
begin
   if bo.ClassName <> ListClassName then begin
      MessageDlg('Sig xom ara gaq !!', mtError, [mbOK],  0 );
      Exit;
   end;
   SetLength(Items, Length(Items) +  1 );
   Items[Length(Items)- 1 ] := bo;
end;

constructor TArrayOfClasses.Create(C : TBaseClassClass);
begin
   ListClassName := C.ClassName;
   SetLength(Items,  0 );
end;

var
   CList : TArrayOfClasses;
begin
  // GAMOYENEBIS MAGALITI: ...
  CList := TArrayOfClasses.Create(TClass1);
  CList.Add(TClass1.Create); // GOOD
  CList.Add(TClass2.Create); // ERROR
  CList.Free;
end.


это хотел?
...
Рейтинг: 0 / 0
24.09.2003, 14:30
    #32274188
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Приблизительно да. Спасибо.

А что происходит с памятью выделяемой в строках
CList.Add(TClass1.Create); // GOOD
CList.Add(TClass2.Create); // ERROR
Кажется она не очищается....?

Но, как обычно, "с перламутровыми пуговицами" предпочтительней. Т.е очень хочется проверку делать не на уровне не совпадения с внутренним эталонным именем, а на уровне не совпадения типов.

Поясните, что у zDIV означает класс TTaskFormClass?
...
Рейтинг: 0 / 0
24.09.2003, 14:36
    #32274199
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
память конечноже НЕ очищается.
Я тоже не понял что это за класс TTaskFormClass.

Т.е. ты хочеш чтоб тебе компилятор выдавал бы ошибку несовпадения типов??
Это исключено в принципе т.к ты ведь создаёш класс который потенциально предназначен для любоко потомка базового, откуда же компилятор может знать ПРИ КОМПИЛЯЦИИ для которого конкретного класса ты собираешся его использовать?
...
Рейтинг: 0 / 0
24.09.2003, 15:02
    #32274257
zDIV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
TTaskFormClass = class of TTaskForm
TObjectList самостоятельно освобождает память своих объектов в отличие от других вариантов (более достойной альтернативой, по-моему, здесь является TCollection)!!!
Необходимо изменить
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function TTaskFormList.CheckObject(AObject: TObject): Boolean;
begin
  Result := Assigned(AObject) and (AObject is FTaskFormClass); // 1 ) не заработает;  2 ) если нужна ошибка
end;

function TTaskFormList.CheckObject(AObject: TObject): Boolean;
begin
  Result := Assigned(AObject) and (AObject.ClassName = FTaskFormClass.ClassName);
  if not Result then Exception.Create('Boroda');
end;
...
Рейтинг: 0 / 0
24.09.2003, 15:07
    #32274271
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Это я понимаю. Но надеюсь на "run time error", ловящийся по try. Типа "авто проверки" изменяемых (добавляемых) записей. Согласись, было бы красиво, особенно авто "прикост" к дочерниму типу.
...
Рейтинг: 0 / 0
24.09.2003, 15:10
    #32274283
zDIV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Пардон...

function TTaskFormList.CheckObject(AObject: TObject): Boolean;
begin
Result := Assigned(AObject) and (AObject.ClassName = FTaskFormClass.ClassName);
if not Result then raise Exception.Create('Boroda');
end;

Очевидно, в этом случае можно обойтись и

procedure TTaskFormList.CheckObject(AObject: TObject);
...
Рейтинг: 0 / 0
24.09.2003, 15:10
    #32274284
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Спасибо
...
Рейтинг: 0 / 0
24.09.2003, 15:11
    #32274287
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Хотя если писать на C++ и использовать шаблоны (Template) то можно добиться такого результата (ошибка при компиляции). Но шаблоны на самом деле создают много разных классов и это тоже самое если просто в Delphi создать идентичние объекты для всех классов-потомков.
...
Рейтинг: 0 / 0
24.09.2003, 15:13
    #32274292
BaseAdmin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
Кстати... А в Delphi аналог Temlate есть?
...
Рейтинг: 0 / 0
24.09.2003, 15:17
    #32274298
GroZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
не понял на счёт авто "прикоста" к дочерниму типу. .. как ты это себе представляеш?

>>надеюсь на "run time error", ловящийся по try. Типа "авто проверки"
>>изменяемых (добавляемых) записей.

какая проблема? вместо MessageDlg(..); делай raise ...

в Delphi аналогов Temlate вроде нет.
...
Рейтинг: 0 / 0
24.09.2003, 17:55
    #32274583
Mik Prokoshin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать тип?
2 BaseAdmin:
Привести из одного дочернего типа в другой - никак не удастся штатными методами - нет таких у компилятора. Попробуй для примера, данного GroZ, написать где-нибудь :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
var
a:TClass1;
b:TClass2;
c:TBaseClass;
...
c:=a;  // Без проблем
c:=b;  // Без проблем
c:=a as TBaseClass;  // Без проблем
c:=a as TClass2;  // Ошибка
c:=(a as TBaseClass) as TClass2;  // Все равно ошибка


И это логично, т.к. компилятор не может предполагать идентичность интерфейса базового класса и его потомка. Как правило, в потомка добавлено что-то "свое", что компилятор никак не может "выбросить".

Из того же примера : Вы можете создавать экземпляр объекта нужного Вам типа для массива и копировать его атрибуты из того объекта, что пытаемся присвоить. Естественно, что в этом случае, в списке будут не непосредственно присваиваемые классы, а их копии:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
   TArrayOfClasses = class
   private
      ListClassClass : TBaseClassClass;
   public
      Items : array of TBaseClass;
      procedure Add(const bo : TBaseClass);
      constructor Create(C : TBaseClassClass);
   end;

....

procedure TArrayOfClasses.Add(const bo: TBaseClass);
var bo1 : TBaseClass;
begin
   bo1 := ListClassClass.Create;
   bo1.Assign(bo);
   SetLength(Items, Length(Items) +  1 );
   Items[Length(Items)- 1 ] := bo1;
end;

Также надо будет позаботиться о методе TBaseClass.Assign и об уничтожении созданных копий объектов. Я проверил - работает : на запрос i-го элемента возвращается именно объект заданного типа, какой бы ни присваивали.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как передать тип? / 25 сообщений из 25, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]