powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как передать тип?
25 сообщений из 25, страница 1 из 1
Как передать тип?
    #32273018
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть набор классов, наследников базового.
Надо сделать класс-массив их (один на всех). В одном экземпляре массива должны находиться экземпляры только одного из классов.
Как в конструктор передать тип класса наследника и отслеживать вызов методов (например, Add) с экземпляром другого класса в качестве параметра?
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #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
Как передать тип?
    #32273086
Фотография GroZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Малиновский Владимир,
Что это !?
...
Рейтинг: 0 / 0
Как передать тип?
    #32273109
Малиновский Владимир
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот и я о том же
...
Рейтинг: 0 / 0
Как передать тип?
    #32273126
Малиновский Владимир
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arr_class := TMyClass1.Create;
arr_class := TMyClass2.Create;
...
Рейтинг: 0 / 0
Как передать тип?
    #32273134
Малиновский Владимир
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то у меня квадратные скобки с индексами массива не выводятсся в опубликованную ерунду... Только шрифт меняется...
...
Рейтинг: 0 / 0
Как передать тип?
    #32273253
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Потому, что они в тэги преобразовываются - вот и не выводятся. Наверное где-то на форуме написано, чё с ними делать, если показать надо.
...
Рейтинг: 0 / 0
Как передать тип?
    #32273582
Mik Prokoshin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Делается массив для базового класса. Все наследуемые могут в нем спокойно содержаться. Естественно, что оперировать без явных преобразований можно только методами базового класса (с учетом virtual). А то, что Вы пытаетесь сделать попахивает мультиметодами (методами, применимыми к разным классам). Не советую :-)
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #32273851
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возможно я не совсем корректно сформулировал мысль.
Есть базовый класс, есть его наследники с интерфейсом базового класса, есть класс - набор наследников (на основе TList). В одном экземпляре класса-набора могут содержаться дофига элементов, но все - одного класса-наследника. Ситуация когда в наборе содержатся различные наследники недопустима. Чтобы не создавать кучу потомков набора (для каждого наследника свой) есть такая "идея":
При создании экземпляра класса-набора в параметре constructor-а предается тип содержания. Например так: MyList:=TMyList.Create(TMyType1);
Все добавляемые в набор классы костятся к TMyType1.
Т.к. прикостить наследника можно только к родителю, а не к "брату" (или я ошибаюсь?), то попытка добавления в набор "брата" приведет к ошибке, чего я и добиваюсь. Вопрос: Как передать тип в Create, а затем использовать его для приведения? Т.е. чего писать в constructor Create(A:????)
и как потом приводить List ^ к типу А.
На данный момент я все привожу к базовому классу, что позволяет создавать "смешенные наборы", а это не допустимо.
...
Рейтинг: 0 / 0
Как передать тип?
    #32273943
m_kus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Класс передать можно так:
Код: plaintext
1.
2.
3.
4.
type TItemClass=class of TItem;
...
type TMyList=class(TList);
  constructor Create(A:TItemClass);

Что насчёт того, как приводить, то не знаю, сам разбирайся...
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #32274027
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TTaskFormClass ?????????
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #32274188
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приблизительно да. Спасибо.

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

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

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

Т.е. ты хочеш чтоб тебе компилятор выдавал бы ошибку несовпадения типов??
Это исключено в принципе т.к ты ведь создаёш класс который потенциально предназначен для любоко потомка базового, откуда же компилятор может знать ПРИ КОМПИЛЯЦИИ для которого конкретного класса ты собираешся его использовать?
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #32274271
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это я понимаю. Но надеюсь на "run time error", ловящийся по try. Типа "авто проверки" изменяемых (добавляемых) записей. Согласись, было бы красиво, особенно авто "прикост" к дочерниму типу.
...
Рейтинг: 0 / 0
Как передать тип?
    #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
Как передать тип?
    #32274284
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо
...
Рейтинг: 0 / 0
Как передать тип?
    #32274287
Фотография GroZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя если писать на C++ и использовать шаблоны (Template) то можно добиться такого результата (ошибка при компиляции). Но шаблоны на самом деле создают много разных классов и это тоже самое если просто в Delphi создать идентичние объекты для всех классов-потомков.
...
Рейтинг: 0 / 0
Как передать тип?
    #32274292
BaseAdmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кстати... А в Delphi аналог Temlate есть?
...
Рейтинг: 0 / 0
Как передать тип?
    #32274298
Фотография GroZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не понял на счёт авто "прикоста" к дочерниму типу. .. как ты это себе представляеш?

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

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

в Delphi аналогов Temlate вроде нет.
...
Рейтинг: 0 / 0
Как передать тип?
    #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
25 сообщений из 25, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как передать тип?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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