Как использовать помощников класса для доступа к строгим закрытым членам класса?
Это дополнительный вопрос к: Как скрыть защищенную процедуру объекта?
(Я немного нечеткий в отношении всей концепции помощника класса)
Предположим, у меня есть такой класс:
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.