0

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)?

Pubby
  • 51,882
  • 13
  • 139
  • 180
Rafik Bari
  • 4,867
  • 18
  • 73
  • 123
  • 4
    Why exactly is there a `c++` tag here? – Chris Eberle Dec 22 '11 at 20:54
  • maybe because the question is also answerable by someone else who uses c++ 1O1 – Rafik Bari Dec 22 '11 at 20:55
  • 1
    No, that's not how this works. You don't choose your audience, you describe the content. – Chris Eberle Dec 22 '11 at 20:57
  • I'm removing all the tags but delphi. If it doesn't relate to a specific version then don't add the tags (if it does then add one back in). Also, your sentences don't make much sense. – Pubby Dec 22 '11 at 20:57
  • 4
    The question is either so extremely basic that a link to a Delphi book or tutorial would do, or I simply didn't get it at all. – Uwe Raabe Dec 22 '11 at 21:04
  • @UweRaabe Do you have the link to the delphi book which can solve my question ? – Rafik Bari Dec 22 '11 at 21:07
  • http://www.amazon.com/exec/obidos/ASIN/1440480117/marcocantusde-20 – Uwe Raabe Dec 22 '11 at 21:11
  • 3
    Is the question similar to "How can I declare variables in a unit in a way that they are usable from other units?"? – Uwe Raabe Dec 22 '11 at 21:14
  • 1
    Are you sure you want to have shared global variables as your primary coupling mechanism? – David Heffernan Dec 22 '11 at 22:52
  • 2
    For the definitive guide, look at the [Delphi Language Guide](http://docwiki.embarcadero.com/RADStudio/en/Delphi_Language_Guide_Index), specifically [Programs and Units](http://docwiki.embarcadero.com/RADStudio/en/Programs_and_Units_Index). You might also try http://delphi.about.com for general Delphi programming information, as well as some more advanced subjects. Using different units and the visibility of things in the interface and implementation sections is really basic information, and should be pretty easy to find. – Ken White Dec 23 '11 at 03:31

2 Answers2

7

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?

Community
  • 1
  • 1
Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
  • BTW, the docs for XE2 are there. See the links in my comment to the original post. :) – Ken White Dec 23 '11 at 03:33
  • @Jerry, how does your answer explain that? Both explain how to define variables and types in a unit that can be seen from another unit; the fact you need to `use` the common unit is presumed by both answers. (You just add it to the `interface` uses clause (or better, the `implementation` uses) of the other units that need to "see" the definitions or variables, like you would the `Windows` or `Classes` unit, BTW, in order to make it clear.) – Ken White Dec 23 '11 at 03:35
  • @KenWhite The `uses` clause underneath the `implementation` – Jerry Dodge Dec 23 '11 at 03:37
  • @Jerry, must have missed it in the other stuff. And it's actually not factually correct, as you can use it in either the `interface` or `implementation` as needed. See `Windows`, `Classes`, `Forms`, or any of the other Delphi VCL/RTL units for examples of doing so. – Ken White Dec 23 '11 at 03:38
  • @KenWhite Units used in the `interface` section cannot be cross-referenced, but units used in the `implementation` section can. That's my point. But I wish the question was a little more clear and my answer would have been more clear and directed at the specific issue. – Jerry Dodge Dec 23 '11 at 03:44
  • 1
    @Jerry, two points (and then discussion concluded): 1) Perhaps you should avoid answering until you've asked for and gotten clarification first?, and 2) your last comment about your "point" makes no sense - I posted example units that can be used in the `interface` sections of multiple others without causing cross-reference problems, and your first sentence (before "That's my point." is really obscure and confusing. I don't know what it means, and we've been at this for a while. ;) Regardless, this isn't a chat room, and I think we're done here. :) – Ken White Dec 23 '11 at 03:52
  • Just to clarify, my first comment on this answer was directed at Marcus, the person who answered, although I didn't directly mention their name. – Jerry Dodge Dec 23 '11 at 04:30
  • @KenWhite I used the wrong word then. "Circular-Reference" not "Cross-Reference". Meaning, Unit A can use Unit B, and at the same time Unit B can use Unit A. You can't do that if you declare the unit under interface. – Jerry Dodge Dec 23 '11 at 04:45
  • @Jerry, then you did *indeed* miss the point of the question. The question was "How do I create a UnitC that can then be used in both UnitA and UnitB without causing circular references?" UnitC can then be used in both UnitA and UnitB interface (or implementation) sections perfectly well. – Ken White Dec 23 '11 at 11:58
2

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.

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • 1
    Your first paragraph is wrong. :) In recent versions of Delphi, a "namespace" can be spread over multiple units. For instance, in Delphi XE2, the entire `VCL` namespace consists of many, many units, as does the 'FMX` namespace. The introduction of generics resulted in two units that are part of that namespace (`Generics.Defaults` and `Generics.Collections`). – Ken White Dec 23 '11 at 02:18
  • Ahh, I did not know that as I am acquainted with Delphi 7. I will soon be installing XE2 though :D Please feel free to edit my answer and correct them, as it appears I know nothing of this new subject. Thanks for the tip! – Jerry Dodge Dec 23 '11 at 02:39
  • Jerry, you might want to edit it yourself. If I start, I'd trim about half of it as unnecessary info that, while useful, confuses the issue asked about in the original question. :) Sometimes there's such a thing as "too much information" that in the long run might be helpful, but in the short term obscures the part that is immediately needed. If you ask me how to replace the RAM modules in your computer, and I start explaining how the CPU works, binary numbers, GPUs, hard disks, and random vs. sequential access to data, you miss the 2 or 3 sentences about how to change memory modules. :) – Ken White Dec 23 '11 at 02:45
  • @KenWhite Done. I was a little unclear what the question was actually trying to ask, so I explained the main important parts of structuring a unit. – Jerry Dodge Dec 23 '11 at 02:50
  • First paragraph is much better. As far as the rest, the question was "How do I declare variables in a unit that then can be used in other units without circular reference errors?", which @MarcusAdams answered rather well (4 hours earlier) in his first paragraph, and then illustrated with a code sample. (Not downvoting your answer, just for the record.) :) – Ken White Dec 23 '11 at 03:01
  • @KenWhite Understood - but without certain other comments, someone may attempt to put a 'var' section before the 'uses' section, or other similar things which of course won't work. And trust me - the code was originally twice as long with a constructor/destructor in TMyObject, other different types, and much more - which I deleted before I posted the answer for your exact reason. I believe at least 80% of the code is perfectly relevant, and the other 20%, does it really matter that much? – Jerry Dodge Dec 23 '11 at 03:08
  • I'd actually reverse your percentages. :) About 20% was relevant to the question asked, and 80% was (useful at some point but) unnecessary in answering that question. Glad you didn't post your original. :) We're over-discussing this issue, I think. – Ken White Dec 23 '11 at 03:18
  • @KenWhite Ok, since you absolutely insist, I removed even more "unnecessary" code. And I see nothing in Marcus' answer related to circular reference. – Jerry Dodge Dec 23 '11 at 03:32