Как создать метакласс всех предков?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Danila
незнакомец
Сообщения: 1
Зарегистрирован: 27.10.2017 11:37:11

Как создать метакласс всех предков?

Сообщение Danila »

Возможно ли создать метакласс всех предков? Если да, то как?
Например:
У меня есть класс Tool, а его потомки Fig и Zoo, а у Fig и Zoo тоже есть потомки. Как создать метакласс для Tool, чтобы можно было достучатся до потомков Fig и Zoo?
Аватара пользователя
Cheb
энтузиаст
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34
Контактная информация:

Сообщение Cheb »

Код: Выделить всё

type 
   CTool = class of TTool;
var
  t: TTool;
  c: CTool;
...
  c:= TZoo;
...
  t:= TTool(c.Create()); //уже забыл, зачем приведение типа нужно, но оно нужно.


P.S. Переменной предкового типа можно присваивать любых потомков этого типа - естественно, знать она будет только о тех методах, что есть у этого предкового типа. Для того механизм виртуальных методов и нужен. Чтобы код мог работать с потомками, как с чёрными ящиками, не подозревая о том, что это уже не предок.

P.P.S. Если нужно копать глубже, возможны извращения типа

Код: Выделить всё

  if t is TZoo then with TZoo(t) do begin
    ZooDo();
  end;

или, но это уже бомбанёт исключением, если t - не TZoo, а, например, TCarFactory:

Код: Выделить всё

  (t as TZoo).ZooDo();
olegy123
долгожитель
Сообщения: 1643
Зарегистрирован: 25.02.2016 11:10:20

Сообщение olegy123 »

Код: Выделить всё

TTool = class if(..)
TFig=Class of (TTool);
TZoo=Class of (TFig);

var
  tool_obj:TTool;
  fig_obj:TFig;
  zoo_obj:TZoo;
  dymmu_obj:TObject;
  PTool:^TTool;
  pointer_obj:TPointer;

tool_obj:=TTool(zoo_obj);
или
tool_obj:=zoo_obj as TTool;
также можно указать в обратном
zoo_obj:=TZoo(tool_obj);

dymmu_obj:=TObject(zoo_obj)
tool_obj:=TTool(dymmu_obj);

pointer_obj:=@zoo_obj;
tool_obj:=PTool(pointer_obj)^;

tool_obj, fig_obj, zoo_obj - это указатели на участок памяти в котором располагаются данные объекта. Тем самым компилятор понимает что применять нужно с данным объектом. Принудительно приводим одно к другому, даже через pointer, Компилятор не возмущается, считая что мы понимаем что делаем.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

Приведение не нужно, а вот что нужно — отметить конструктор предка как virtual и в потомках его override'ить, иначе для class of T статически вызовется конструктор T вместо правильного. (Собственно, в этом случае class of — встроенный в язык шаблон «фабричный метод», который по-другому так и называется — «виртуальный конструктор»).
Ответить