Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

До, включая 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 теперь зафиксировал в Берлине. Вам не повезло.

Ответ 2

Доступ к 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.