Rafik Bari
Rafik Bari

Reputation: 5037

To avoid circular references. How to create a new unit and put all needed variables within?

How do I create a unit in order to call it after that by adding it to the uses clause of the implementation part of 3 other units?

When I first create a unit I see something like:

unit Unit1;

interface

implementation

end.

How do I put some variables which I am using in my script in order to re-call them from 3 other units (to avoid circular references)?

Upvotes: 0

Views: 1162

Answers (2)

Marcus Adams
Marcus Adams

Reputation: 53860

Global variables, classes, methods, constants, and public members defined in the Interface section are all available to reference in other units.

unit Unit1;

interface

const
  // Global constant
  MY_CONSTANT = 'FOO';

type TMyObject = class
private
  FMyProperty: String;
public
  // Public instance variable of class TMyObject
  myPublicInstanceVariable: String;
  // Public property of class TMyObject
  property MyProperty: String read FMyProperty;
end;

var
  // Global variable
  myStringVariable: String;

implementation

end.

Protected members are available from other units within an inherited class.

Unfortunately, the documentation in XE2 is rather sparse. If you had an earlier version of Delphi, everything you needed to know about the basics would be included in the online help.

Edit

My answer to this question gives more details about uses clauses and avoiding circular references:

How to manage circular references in delphi units?

Upvotes: 7

Jerry Dodge
Jerry Dodge

Reputation: 27276

A Delphi "Unit" is basically the same thing as a "Namespace". In other languages such as C#, a namespace can be declared in many different units (files). But in older versions of Delphi, 1 single unit represents an entire "namespace". Newer versions of Delphi have new namespace capabilities, which I won't cover, because I don't know about these new abilities.

It was a little hard to understand exactly what you are asking, so here are the basics of structuring a unit in Delphi.

There are many different things you can put in a raw unit. It all depends on the purpose of the unit. At the very top, just under interface, is where you begin declaring things. You can declare uses, constants, types, variables, methods, etc. The order of these sections should be in the order of the unit below (and I'm sure I'm probably missing something).

To avoid circular-referencing, you are able to declare a uses clause beneath the implementation section. This is only usable to the code below it, and not to the code above it. See below. You can have two units use each other (A using B and B using A) if you put your unit in the implementation section, but you can't if you put it in the interface section.

unit MyUnit;

interface

uses
  { Whatever other units you need to use }
  { These are other unit files (or namespaces) you need for your code below }
  Classes, SysUtils, Windows;

const
  { Whatever constants you would like to add }
  { These are static and cannot be changed programmatically }
  SOME_INT_CONST = 123;
  SOME_STR_CONST = 'Some Constant';

type
  { Whatever types you would like to add }
  { These are your own types and should all be prefixed with the capital letter 'T' }
  TMyObject = class(TObject)
  private
    FSomeField: String;
    procedure SetSomeField(const Value: String);
  public
    property SomeField: String read FSomeField write SetSomeField;
  end;

var
  { Whatever variables you would like to add }
  { This I believe is what you intend by your question }
  SomeVar: String;
  SomeObject: TMyObject;

{ Finally whatever global methods you would like to add }
{ These methods will be available from any other unit which uses this unit }
procedure DoSomething(SomeParam: String);

implementation

uses
  { Whatever other units you need to use }
  { This can be used in 2 units and cross-reference each other, if needed }
  { but can only be used in implementation below, not in anything above }
  { This I believe should solve your 'circular reference' issues }
  MyOtherUnit;

procedure DoSomethingElse;
begin
  { This procedure isn't declared above, so it won't be available to other units }
  { Only things declared in `interface` can be accessed from other units. }
end;

procedure DoSomething(SomeParam: String);
begin
  //Whatever code needed to do something with 'SomeParam'
  if SomeParam = SOME_INT_CONST then begin
    ShowMessage('They are the same!');
  end;
end;

procedure TMyObject.SetSomeField(const Value: String);
begin
  if FSomeField <> Value then begin
    FSomeField:= Value;
    DoSomething(Value);
  end;
end;

end.

There isn't any such thing as "calling a unit" - as long as it is in your uses clause, it will automatically be included and compiled in your project. You don't call the unit, you call things in the interface of that unit.

Upvotes: 2

Related Questions