This is a follow-up question to: How to hide a protected procedure of an object?
(I'm a bit fuzzy on the whole class helper concept)
Suppose I have an class like:
type TShy = class(TObject) strict private procedure TopSecret; private procedure DirtyLaundry; protected procedure ResistantToChange; end;
I know I can access the private method if I have the source code by adding a descendent class in the same unit.
I have 2 questions:
- How do I employ a class helper to access the strict private
member?
- Can I use a class helper in a separate unit to access (strict) private members?
Up to, and including Delphi 10.0 Seattle, you can use a class helper to access strict protected
and strict private
members, like this:
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;
However, starting with Delphi 10.1 Berlin, this no longer works! Class helpers can no longer access strict protected
, strict private
or private
members. This "feature" was actually a compiler bug that Embarcadero has now fixed in Berlin. You are out of luck.
Access to private
and strict private
members of a class with class helpers
was removed in Delphi 10.1 Berlin. See Closing the Class Helpers Private Access Loophole.
But there is still an open loophole:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With