Nested record information hiding in Delphi
I have a relatively complicated data structure to model. I would like to do this with a record structure in Delphi, and the structure is complicated enough to justify splitting this into nested records. A simplified example:
type
TVertAngle = record
strict private
fDecDegrees: Double;
fDegrees: integer;
fMinutes: integer;
fDeciSeconds: integer;
function GetAngle: Double;
function GetRadians: Double;
public
Valid: Boolean;
procedure SetAsString(const Value: string; const AngleType: TInfoUnits);
property DecDegrees: Double read GetAngle;
property Radians: Double read GetRadians;
end;
~~~~ other sub record declarations ~~~~~~
TDataRecord = record
strict private
fHorzDistance: Double;
fLeicaData: TRawMessageData;
fUpdateTime: TDateTime;
function DecodeGsi8(GsiWord: string): TGSiWord;
function DecodeGsi16(GsiWord: string): TGSiWord;
public
GsiWord: TGSiWord;
Valid: Boolean;
InputMode: TDataModes;
HorzAngle: THorzAngle;
VertAngle: TVertAngle;
HorzRange: TDistance;
SlopeRange: TDistance;
PrismOffset: TConstants;
~~~~ other sub record instances~~~~~~
function SetMessage(RawMessage: string): Boolean;
~~~~ more stuff ~~~~~~
I currently have all this declared in the Interface section of the unit. I would prefer if only the main record structure was visible to anything using the unit, and at the moment all the开发者_如何学编程 sub records are also visible. If I move the record declarations into the Implementation section then I get compiler errors. How do I restructure so that I declare the sub-records prior to the main record but the sub-records are not published?
You can do one of the following:
1) Declare "sub records" in a separate "sub unit", so the "sub record" types are available only if the "sub unit" is declared in the "uses" clause. That is not exactly what you are looking for, since the "sub records" can be made visible for other units, but it provides some degree of hiding since the "sub unit" must be explicitely declared to reach "sub record" definitions.
2) Declare "sub records" as private nested types as follows:
type
TMainRec = record
private type
TSubRec = record
FSubField: Integer;
procedure SubMethod;
end;
private
FSubRec: TSubRec;
end;
implementation
{ TMainRec.TSubRec }
procedure TMainRec.TSubRec.SubMethod;
begin
...
end;
You can't do that, because even if the information doesn't need to be directly available to other code outside the unit, the compiler still needs to know about the sub-record types if you're going to use the main record somewhere.
One thing you could try is declaring the other types in another unit and then not using that other unit anywhere else. That doesn't really solve the problem, though; it just hides it a little.
精彩评论