基本クラスの派生クラスのクラス変数を操作する

なぜこれが必要なのですか?



たとえば、クラスをシリアル化するときに、このようなニーズに遭遇しました。 基本クラスの子孫クラスに関するすべてのルーチンコードと情報を取り出したいという要望がありました。 まあ、怠は、結局のところ、各子クラスに同じことを処方することです。 だから私は考え直した、多分私はここでジェネリックを台無しにすることができます。



そのため、必要なクラス変数をレコードにラップし、それらにメモリを動的に割り当ててから、ポインターを介して使用できます。 このポインターは、中間の一般化クラスのクラス変数に格納されます。 この一般化されたクラスは、さまざまなクラス数学の新しい一意の基本クラスになります。



クラスの特定のインスタンスからこのようなデータにアクセスするには、一般化クラスのコンストラクターで初期化されるポインターフィールドを追加します。 そして、このポインターを基本クラスのクラスメソッドに渡すには、追加のパラメーターを使用します。 おそらく隠された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.
      
      






All Articles