I need to fix a third-party component. This component's class has private variable which is actively used by its descendants:
TThirdPartyComponentBase = class
private
FSomeVar: Integer;
public
...
end;
TThirdPartyComponent = class (TThirdPartyComponentBase)
protected
procedure Foo; virtual;
end;
procedure TThirdPartyComponent.Foo;
begin
FSomeVar := 1; // ACCESSING PRIVATE FIELD!
end;
This works because both classes are in the same unit, so they're kinda "friends".
But if I'll try to create a new class in a new unit
TMyFixedComponent = class (TThirdPartyComponent)
procedure Foo; override;
end;
I can't access FSomeVar anymore, but I need to use it for my fix. And I really don't want to reproduce in my code all that tree of base classes.
Can you advise some quick hack to access that private field without changing the original component's unit if it's possible at all?
Expose the value of the private variable by a protected property in TThirdPartyComponent.
In
TMyFixedComponent
class use theMyVar
Property in the procedure which you would like to override.By the use of
class helpers
it's possible to accomplish access to the private parts of the base class from the derived class without loosing type safety.Just add these declarations in another unit:
As can be seen from comments in code,
FSomeVar
is exposed by a class helper from theTThirdPartyComponentBase
class. Another class helper for theTThirdPartyComponent
implements the Foo procedure. In there, access to theSomeVar
property of the base class helper is made via a type cast to the base class.Don't know if this will help, but I seem to recall there is a way to "crack" a private variable into visibility.
I know, for example, I've encountered warnings from the compiler when I've moved a property from lower visibility (in the base class) to a more visible level (in my descendant). The warning stated that it's being declared at a different level of visibility...
It's been some time and I'm not certain, but I believe what you can do is in your descendant declare the same variable as protected. (You may have to use the Redeclare keyword for this to compile.)
Sorry I don't have more specific information on how to do this (if it's indeed possible.) Perhaps this posting will prompt one of the wizards here into correcting me! :-)
You have to use a hack to access a private field in any class (including a base class) in a different unit. In your case define in your unit:
Then get the access:
Of course, that is dangerous, because you will need to control changes in the base class. Because if the fields layout will be changed and you will miss this fact, then the above approach will lead to failures, AV's, etc.