Reputation: 76670
I have a class that I want to keep private, because I only use it in the implementation section. However it is used by a class that is declared public in the interface section.
Is there a way to do something like this:
unit x;
interface
type
TPrivate = class; //forward declaration
TPublic = class(TSomething)
private
FPrivate: TPrivate;
procedure DoStuffWithFPrivate;
public
//...
end;
implementation
type
TPrivate = class(TObject)
procedure Test;
end;
Obviously the above code gives an error:
[dcc32 Error] UnitX.pas(27): E2086 Type 'TPrivate' is not yet completely defined
I don't want to resort to cheap tricks like:
FPrivate = TObject
....
procedure TPublic.DoStuffWithFPrivate;
begin
TPrivate(FPrivate).Test;
Is there a way to do what I want without having to spill TPrivate
's internal details in the interface?
I know it's possible to declare TPrivate as a strict private
sub type of TPublic, however I don't like the pollution of the interface section this gives.
Is there a way to keep TPrivate
out the of interface
section (as much as possible) whilst maintaining type safety?
Upvotes: 1
Views: 1418
Reputation: 31433
I'm not sure what exactly your definition of "pollution" is as regards the interface section, but if it's just a matter of keeping it from drowning your TPublic
class definition with noise then one option might be simply inheritance :
TBasePublic = class(TSomething)
private
type
TPrivate = class
// ...
// ... keep TPrivate definition separate
end;
end;
TPublic = class(TBasePublic)
private
FPrivate : TPrivate;
end;
This would even allow you to define TPrivate
in a completely different unit if segregation is your goal.
Upvotes: 2
Reputation: 47758
As long as TPrivate
is not used anywhere in the interface of TPublic
besides the field declaration (f.i. as a methods parameter type) you can use a local class helper
to achieve this.
Note: FPrivate
is not a good name for that field!
interface
type
THiddenActual = class
end;
TPublic = class
private
FActual: THiddenActual;
procedure DoStuffWithFPrivate;
public
end;
implementation
type
TActual = class(THiddenActual)
public
procedure Foo;
end;
type
TPublicHelper = class helper for TPublic
private
function GetActual: TActual;
procedure SetActual(const Value: TActual);
public
property Actual: TActual read GetActual write SetActual;
end;
procedure TActual.Foo;
begin
end;
function TPublicHelper.GetActual: TActual;
begin
Result := FActual as TActual;
end;
procedure TPublicHelper.SetActual(const Value: TActual);
begin
FActual := Value;
end;
procedure TPublic.DoStuffWithFPrivate;
begin
Actual.Foo;
end;
OK, it is merely a little variance of that cheap trick, but what are the alternatives? You have to take what is available, don't you?
Upvotes: 4