views:

201

answers:

2

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?

+1  A: 

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.

Mason Wheeler
So within the Unit structure there is not equivalent of the public / private / published concept that exists in class or record declarations? I can see that the compiler needs to see the sub-records, but then doesn't the compiler needs to see the Private declared variables in a class that are not visible outside the class?
HMcG
No it doesn't exist, and yes, it could be solved the same way as classes. But if you add syntax for every theoretic case, all you have to do is "C"ify a few operators and keywords, and you have turned Pascal into Ada :-)
Marco van de Voort
From Wikipedia 'Ichbiah publicly stated that within ten years, only two programming languages would remain, Ada and Lisp.'You've just got to laugh.
HMcG
+4  A: 

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;
Serg
Thanks for the answer. Nesting the sub types within the main record gives me what i want. I had not realized that this was available. Cheers.
HMcG