如何使用类助手访问类的严格私有成员?

29

这是一个跟进问题:如何隐藏对象的受保护过程?
(我对类助手的整个概念有点模糊)

假设我有一个类,像这样:

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

我知道如果我有源代码,可以通过添加一个子类来访问私有方法。

我有两个问题:
- 如何使用类助手访问严格私有的成员?
- 我可以在不同的单元中使用类助手来访问(严格)私有成员吗?


2个回答

38

截至Delphi 10.0 Seattle版本,您可以使用类帮助器来访问strict protectedstrict 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 Berlin版本开始,这不再起作用!类助手不能再访问strict protectedstrict privateprivate成员。这个“功能”实际上是一个Embarcadero已经在柏林修复的编译器错误。你很遗憾无法使用这个操作了。


2
JFTR:在D2007中,Self.DirtyLaundry;Self.ResistantToChange;这两行无法编译,而Self.TopSecret;却可以。也就是说,你可以访问strict private成员,但不能访问privateprotected成员。:-D - Uli Gerhardt
3
这在 Delphi 10.1 Berlin 中已被归类为编译器错误并得到修复,因此不再适用于私有成员。 - Stefan Glienke
4
请参阅 RSB-1146 Fix for "Class helpers allow cross-unit private violations" breaks existing code 和 Marco 在 RSB-1254 can't access to private fields in helpers 上的评论,例如“*[访问助手中的私有变量]被提出作为一个错误,这是正确的。研发部门不知道这种黑客行为。我们考虑过保留这个错误,但最终决定不这样做。这是一个太基本的问题了]*”。 - Remy Lebeau
你说:“严格保护和严格私有”那“私有”呢?在柏林也是禁止的吗? - Johan
1
如果你在类助手中定义了私有方法,那么你也无法在自己的代码中访问它。很好... - Z.B.
显示剩余10条评论

8

在 Delphi 10.1 Berlin 中,使用 class helpers 访问类的 privatestrict 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.

1
你刚刚让我一天都很开心。太棒了。 - Johan
3
很抱歉,这个新“特性”并不能完全替代旧的特性,因为它只能让你访问方法,而不能访问字段。在 Delphi 10.1 Berlin 之前,我们还可以访问该类的私有字段。 - Alexandre M
1
要访问私有字段,请参见如何在没有帮助程序的情况下访问私有方法?。通过使用类助手和RTTI的组合,可以保持性能。 - LU RD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接