Delphi 10.1 Berlin では、プライベート メソッドclass helpers
へのアクセスに使用する方法がまだあります。
type
TBase2 = class(TObject)
private
procedure UsefullButHidden;
procedure VirtualHidden; virtual;
procedure PreviouslyProtected; override;
end;
TBase2Helper = class helper for TBase2
procedure OpenAccess;
end;
procedure TBase2Helper.OpenAccess;
var
P : procedure of object;
begin
TMethod(P).Code := @TBase2.UsefullButHidden;
TMethod(P).Data := Self;
P; // Call UsefullButHidden;
// etc
end;
残念ながら、Delphi 10.1 Berlin では、クラス ヘルパーによって厳密なプライベート/プライベート フィールドにアクセスする方法はありません。RTTI はオプションですが、パフォーマンスが重要な場合は遅いと見なすことができます。
クラス ヘルパーと RTTI を使用して、起動時にフィールドへのオフセットを定義する方法を次に示します。
type
TBase = class(TObject)
private // Or strict private
FMemberVar: integer;
end;
type
TBaseHelper = class helper for TBase
private
class var MemberVarOffset: Integer;
function GetMemberVar: Integer;
procedure SetMemberVar(value: Integer);
public
class constructor Create; // Executed at program start
property MemberVar : Integer read GetMemberVar write SetMemberVar;
end;
class constructor TBaseHelper.Create;
var
ctx: TRTTIContext;
begin
MemberVarOffset := ctx.GetType(TBase).GetField('FMemberVar').Offset;
end;
function TBaseHelper.GetMemberVar: Integer;
begin
Result := PInteger(Pointer(NativeInt(Self) + MemberVarOffset))^;
end;
procedure TBaseHelper.SetMemberVar(value: Integer);
begin
PInteger(Pointer(NativeInt(Self) + MemberVarOffset))^ := value;
end;
これには、遅い RTTI 部分が 1 回だけ実行されるという利点があります。
注: プロテクト/プライベート メソッドへのアクセスに RTTI を使用する
RTL/VCL/FMX は、RTTI を使用した保護/プライベート メソッドへのアクセスの可視性を宣言していません。ローカル ディレクティブ{$RTTI}で設定する必要があります。
他のコードでプライベート/保護されたメソッドへのアクセスにRTTIを使用するには、たとえば次の設定が必要です。
{$RTTI EXPLICIT METHODS([vcPublic, vcProtected, vcPrivate])}