Как использовать помощников класса для доступа к строгим закрытым членам класса?

Это дополнительный вопрос к: Как скрыть защищенную процедуру объекта?
(Я немного нечеткий в отношении всей концепции помощника класса)

Предположим, у меня есть такой класс:

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

Я знаю, что могу получить доступ к закрытому методу, если у меня есть исходный код, добавив потомок класса в том же модуле.

У меня есть 2 вопроса:
- Как я могу использовать помощника класса для доступа к strict private член?
- Могу ли я использовать помощник класса в отдельном модуле для доступа к (строгим) закрытым членам?

2 ответа

Решение

До, включая Delphi 10.0 Seattle, вы можете использовать вспомогательный класс для доступа strict protected а также 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 Berlin, это больше не работает! Помощники класса больше не могут получить доступ strict protected, strict private или же private члены. Эта "особенность" на самом деле была ошибкой компилятора, которую Embarcadero теперь исправила в Берлине. Вам не повезло.

Доступ к private а также strict private члены класса с class helpers был удален в Delphi 10.1 Berlin. См. Закрытие лазейки частного доступа для помощников класса.

Но есть еще открытая лазейка

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.
Другие вопросы по тегам