29

これは、次のフォローアップの質問です。オブジェクトの保護されたプロシージャを非表示にする方法は?
(私はクラスヘルパーの概念全体について少し曖昧です)

次のようなクラスがあるとします。

type 
TShy = class(TObject) 
strict private
  procedure TopSecret;
private
  procedure DirtyLaundry;  
protected 
  procedure ResistantToChange;
end; 

同じユニットに子孫クラスを追加することでソースコードがあれば、プライベートメソッドにアクセスできることはわかっています。

2つの質問があります: -メンバー
にアクセスするためにクラスヘルパーを雇うにはどうすればよいですか?-別 のユニットでクラスヘルパーを使用して(厳密な)プライベートメンバーにアクセスできますか?strict private

4

2 に答える 2

38

strict protectedDelphi 10.0 Seattleまでは、次のようにクラスヘルパーを使用してstrict privateメンバーにアクセスできます。

unit Shy;

interface

type
  TShy = class(TObject)
  strict private
    procedure TopSecret;
  private
    procedure DirtyLaundry;
  protected
    procedure ResistantToChange;
  end;

unit NotShy;

interface

uses
  Shy;

type
  TNotShy = class helper for TShy
  public
    procedure LetMeIn;
  end;

implementation

procedure TNotShy.LetMeIn;
begin
  Self.TopSecret;
  Self.DirtyLaundry;
  Self.ResistantToChange;
end;

end.

uses
  ..., Shy, NotShy;

procedure TestShy;
var
  Shy: TShy;
begin
  Shy := TShy.Create;
  Shy.LetMeIn;
  Shy.Free;
end;

ただし、Delphi 10.1ベルリン以降、これは機能しなくなりましたstrict protectedクラスヘルパーは、strict privateまたはprivate メンバーにアクセスできなくなります。この「機能」は、実際にはEmbarcaderoがベルリンで修正したコンパイラのバグでした。あなたは運が悪い。

于 2012-02-23T09:57:36.223 に答える
8

Delphi 10.1ベルリンでは、クラスへのアクセスとprivateそのstrict privateメンバーclass helpersが削除されました。クラスヘルパーのプライベートアクセスの抜け穴を閉じるを参照してください。

しかし、まだ抜け穴が開いています。

unit Shy;

interface

type
  TShy = class(TObject)
  strict private
    procedure TopSecret;
  private
    procedure DirtyLaundry;
  protected
    procedure ResistantToChange;
  end;

implementation

procedure TShy.DirtyLaundry;
begin
  WriteLn('DirtyLaundry');
end;

procedure TShy.ResistantToChange;
begin
  WriteLn('ResistantToChange');
end;

procedure TShy.TopSecret;
begin
  WriteLn('TopSecret');
end;

end.

Program TestClassHelpers;

{$APPTYPE CONSOLE}

Uses
  Shy;

type
  TNotShy = class helper for TShy
  public
    procedure LetMeIn;
  end;

procedure TNotShy.LetMeIn;
var
  P : procedure of object;
begin
  TMethod(P).Code := @TShy.TopSecret;
  TMethod(P).Data := Self;
  P; // Call TopSecret
  TMethod(P).Code := @TShy.DirtyLaundry;
  TMethod(P).Data := Self;
  P; // Call DirtyLaundry;
  Self.ResistantToChange;  // Protected access works without problems
end;

var
  myObj: TShy;
begin
  myObj := TShy.Create;
  try
    myObj.LetMeIn;
    ReadLn;
  finally
    myObj.Free;
  end;
end.
于 2016-06-11T08:26:37.927 に答える