Link to home
Start Free TrialLog in
Avatar of TonyDelphiHunt
TonyDelphiHuntFlag for Afghanistan

asked on

Difference between Interface Uses and Implementation uses?

Hi,
I am confused about the difference between the 2 different places where the 'Uses' clause occurs.
In quite a large application, I have been placing them all in the Interface section. There are in excess of 100 units now.

I'd be grateful if someone could explain why there 2 places to put them and how should I decide where to put each used unit...

Avatar of ahalya
ahalya
Flag of Canada image

You would place only things needed in the interface section in the "interface uses".  All others should be placed in the "implementation uses".



To elaborate a little more on the above comment:

It wouldn't make much difference if you 'use' units in a a fairly simple way.

If you have units that use each other  (A uses B, and B uses A) then you need to use the 'implementation uses'.

Also all 'interface uses' units get compiled first.  So, if you need to ensure that units are compiled (and initialized) in a certain order then this becomes important.  This would be the case if you use the "initialization" section to initialize your variables etc.



Avatar of Geert G
allways add units to the implementation section first
if the compiler complains use it in the interface

basically the place you need a function/procedure/variable you put the unit there
Avatar of TonyDelphiHunt

ASKER

This is SO confusing...........

>>allways add units to the implementation section first
if the compiler complains use it in the interface<<

OK...

>>Also all 'interface uses' units get compiled first. <<

SO... If I 'use ' everything in the Interfaces that will work...

From testing, it appears that WHICHEVER section I put things in, the code still compiles.....

????

> SO... If I 'use ' everything in the Interfaces that will work...

YES.


> From testing, it appears that WHICHEVER section I put things in, the code still compiles.....

that is because your unit is a simple one.  here is a sample that will only compile if 'uses Windows'  is declared in the interface, and not in implementation.

(Uses Forms can be either in interface or implementation.
unit test;
 
interface
 
uses Windows;
 
function GetHandle:HWND;
 
implementation
 
uses forms;
 
function GetHandle:HWND;
 
begin;
  result := Application.Handle;
end;
 
end.

Open in new window

> SO... If I 'use ' everything in the Interfaces that will work...
>YES.
NNNOOOOO !!!!

not if you need circular reference,
if you follow the approach first implementation and then interface that will work too ...

sample

unit1
interface
procA
procB
implementation
uses unit2;
procA
  call procC

unit2
interface
procC
procD
implementation
uses unit1;
procC
  call procB;

you approach would be
unit1
interface
uses unit2;
procA
procB
implementation
procA
  call procC

unit2
interface
uses unit1;
procC
procD
implementation
procC
  call procB;

and this doesn't work as he needs to compile the interface of a section first

btw a unit gets compiled in 2 passes, first the interface part, next the implementation part.
this sample will compile the unit1 interface, unit2 interface and then unit1 implementation, unit2 implementation
Hopefully to make things more clear, not more confusing :)

A Delphi / Pascal unit consists of two different parts:

The interface part (this is the header file, *.h or *.hpp file in C / C++) and the implementation part (the *.c or *.cpp file in C / C++).

The interface part describes what kind of classes and functions there are in the unit, what kind of names they have, what kind of arguments they need, it _only_ describes (hence the name interface, it's an 'interface' to the unit).

The implementation part is the implementation to the interface part in the unit. It's the actual source code described in the interface part, hence the name implementation.

The compiler first compiles all the interface parts from all the units, and then all the implementation parts (this is not exactly how things work, but close enough and helps to understand the problems invovled).

Say you have 2 units, each with a class in it (pseudo code),

unit1:

interface

 type TMyClassA = class(TObject)
 public
  procedure SomeCleverStuff;
 end;

// skipped the rest of the unit...


unit2:

interface

uses unit1;

 type TMyClassB = class(TObject)
 public
  procedure DoSomething(MyClassA: TMyClassA);
 end;

// skipped the rest of the unit



As you can see, TMyClassB has a method (DoSomething) which takes an argument of type TMyClassA. To make this work, you need to add the unit 'unit1' to the uses of unit2.
Where? In the interface part, because information (TMyClassA) is needed in the _description_ of unit2.
In this construction, the compiler will first compile unit1, because it is needed by unit2. This way, when the compiler comes to the interface part of unit2, it finds a reference to TMyClassA, and 'knows' about it, since it found it in unit1 before.


The circular reference mentioned by Geert_Gruwez is when you have the following situation:

unit1:

interface

uses unit2;

 type TMyClassA = class(TObject)
 public
  procedure SomeCleverStuff(MyClassB: TMyClassB);
 end;

// skipped the rest of the unit...


unit2:

interface

uses unit1;

 type TMyClassB = class(TObject)
 public
  procedure DoSomething(MyClassA: TMyClassA);
 end;

// skipped the rest of the unit


Now the compiler has a problem, to compile unit1, it first needs to compile unit2, but for unit2, it first needs to compiler unit1. The reason is that the 'description' (interface) of unit1 uses items from unit2, and the vica versa. This code will not compile! If you ever encounter this situation there are workarounds, but it can also show that your approach is incorrect.
This is the reason why "SO... If I 'use ' everything in the Interfaces that will work..." is not correct.

"From testing, it appears that WHICHEVER section I put things in, the code still compiles....."
This is because you don't have any 'circular references' (units which need each other).


So, bottomline (rule of thumb):
"allways add units to the implementation section first if the compiler complains use it in the interface"
Correct!

If you ever encounter the 'circular reference' problem, come back here with the actual situation...

I hope you understand :)
ASKER CERTIFIED SOLUTION
Avatar of Geert G
Geert G
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Not quite what I was looking for, that's MY FAULT for not knowing the right question to ask!!! BUT there were enough clues to help a lot. Thank You.
Author Comments:
Not quite what I was looking for, that's MY FAULT for not knowing the right question to ask!!! BUT there were enough clues to help a lot. Thank You.

ugh no not really, if you have a problem, then this allways raises the question, how to fix
that off course raises the problem, how to explain the problem to get the fix

so basically a problem allways comes in 3fold

what delphi does is like create a index (the interface) of the implementation
to compile the interface you need to uses the indexes of other units (interface)
and to compile the implementation you need to also possibly uses other indexes (interface)

it comes down to creating a parent-child relationship between the units