Почему это необходимо? С этой необходимостью я столкнулся, например, при сериализации классов.
Было желание весь рутинный код и информацию о классах-потомках переместить в базовый класс.
Ну лень писать одно и то же для каждого дочернего класса.
Поэтому я начал думать, может быть, я мог бы добавить сюда дженерики.
А так, нужные переменные класса можно завернуть в запись, динамически выделить для них память и затем использовать через указатель.
Этот указатель будет храниться в переменной класса промежуточного универсального класса.
Этот обобщенный класс станет новым уникальным базовым классом для различных последующих классов.
Чтобы получить доступ к таким данным из конкретного экземпляра класса, вы можете добавить поле указателя, которое будет инициализировано в конструкторе универсального класса.
А чтобы передать этот указатель методам базового класса, используйте дополнительный параметр.
Подмена значения этого параметра, возможно, вместо скрытого ClassSelf, будет осуществляться в перегруженных методах промежуточного обобщенного класса.
Вариант реализации базовых и универсальных классов:
Пример использования:unit MyStore; interface uses System.Generics.Collections; type TDataBase = class abstract protected type TDataType = class of TDataBase; TDataList = TList<TDataBase>; TDataInfo = array of Integer; PClassVar = ^TClassVar; TClassVar = record cType :TDataType; cObjs :TDataList; cInfo :TDataInfo; end; protected fVar :PClassVar; class function Init(var cVar :PClassVar):Pointer; overload; class procedure Done(var cVar :PClassVar); overload; static; class procedure AddFild( cVar :PClassVar; var Fild); overload; static; public Tag :Integer; procedure Save; constructor Create; virtual; destructor Destroy; override; end; TDataProx<T:class> = class(TDataBase) protected class var cVar :TDataBase.PClassVar; class function Init:T; overload; inline; class procedure Done; overload; inline; class procedure AddFild(var Fild); overload; inline; public constructor Create; overload; override; class function Objs:TList<T>; inline; end; implementation { TDataBase } class procedure TDataBase.AddFild(cVar: PClassVar; var Fild); // static; begin with cVar^ do begin SetLength(cInfo,Length(cInfo)+1); cInfo[Length(cInfo)-1]:=Integer(PByte(@Fild) - PByte(@cType)); end; end; procedure TDataBase.Save; begin with fVar^ do begin end; end; constructor TDataBase.Create; begin with fVar^ do cObjs.Add(Self); end; destructor TDataBase.Destroy; begin with fVar^ do cObjs.Extract(Self); inherited; end; class procedure TDataBase.Done(var cVar: PClassVar); // static; var Obj :TDataBase; begin with cVar^ do begin for Obj in cObjs do begin Obj.Save; Obj.Free; end; cObjs.Free; Finalize(cInfo); end; Dispose(cVar); end; class function TDataBase.Init(var cVar: PClassVar):Pointer; // uses ClassSelf begin New(cVar); with cVar^ do begin cType:=Self; cObjs:=TDataList.Create; Initialize(cInfo); Result:=@cType; // synthetic Object :) end; AddFild(cVar,TDataBase(Result).
Tag); end; { TDataProx<T> } class procedure TDataProx<T>.
AddFild(var Fild); // inline; begin AddFild(cVar, Fild); end; constructor TDataProx<T>.
Create; begin fVar := cVar; // ! inherited; // ! after fVar := cVar; end; class procedure TDataProx<T>.
Done; // inline; begin Done(cVar); end; class function TDataProx<T>.
Init:T; // inline; begin Result:=Init(cVar); end; class function TDataProx<T>.
Objs: TList<T>; // inline begin Result:=TList<T>(cVar.cObjs); end; end.
unit MyData;
interface
uses MyStore;
type
TDataA = class(TDataProx<TDataA>)
Data :Integer;
Note: string;
class constructor Init;
class destructor Done;
class procedure Work;
end;
TDataB = class(TDataProx<TDataB>)
Data :Double;
Memo :array of string;
class constructor Init;
class destructor Done;
end;
implementation
{ DataA }
class destructor TDataA.Done;
begin
Done;
end;
class constructor TDataA.Init;
begin
with Init do begin
AddFild(Data);
AddFild(Note);
end;
end;
class procedure TDataA.Work;
var
Obj :TDataA;
begin
for Obj in Objs do Inc(Obj.Data,Obj.Tag);
end;
{ DataB }
class destructor TDataB.Done;
begin
Done;
end;
class constructor TDataB.Init;
begin
with Init do begin
AddFild(Data);
AddFild(Memo);
end;
end;
end.
Теги: #delphi #дженерики #ООП #delphi
-
Sspp (Парсер Состояния Сервера Php)
19 Oct, 24 -
Менеджер Объектов В Magento 2
19 Oct, 24 -
Логическая Организация Кэш-Памяти Процессора
19 Oct, 24 -
Логик Найт Люксофт
19 Oct, 24