views:

736

answers:

3

I'm just trying to get the hang of separate units to make my code more encapsulated. I'm trying to get the public/private declarations of my methods sorted out, so I can call them from other units that use testunit. In this example I want to make hellofromotherunit public, but stickletters private.

unit testunit;    

interface

uses
  Windows, Messages, Dialogs;    

implementation

function stickletters(a,b:string):string;
begin
  result:=a+b;
end;

procedure hellofromotherunit();
begin
 showmessage(stickletters('h','i'));
end;

end.

I could not seem to copy the private/public structure from other units as in:

Type
private
function stickletters(a,b:inter):integer;
public
procedure hellofromotherunit();
end
+4  A: 

Private & Public only apply to classes.

What you want to do is put a copy of the declaration of hellofromotherunit into the interface section. Do not put a copy of stickletter's declaration up there, however.

Anything that appears in the interface section is effectively public. Anything that's only down in the implementation is private.

Loren Pechtel
+5  A: 

The Unit structure looks a bit like the public/private sections from objects, you could say it is their forerunner. But the syntax is different.

You only have to declare the method header in the interface section, as in:

interface
  procedure hellofromotherunit();

implementation
  procedure hellofromotherunit(); begin .. end;

Only one of each section allowed.

Henk Holterman
A: 

In addition,

Each unit has two distinct parts. The interface and the implementation.

The interface section contains all public definitions (types, procedure headings, constants). The implementation section contains all implementation details.

When you use a unit, (using the uses clause) you get access to the public definitions of that unit. This access is not recursive, so if unit A interface uses unit B, and unit C uses unit A, you do not get access to unit B unless you use it explicitly.

The implementation section has access to the interface, to the unit used in both uses clauses (interface and implementation).

The interfaces of used units are compiled first before it continues compiling the rest. This has the advantage that you can have circular dependencies from within the implementation:

unit A;
interface
uses B;

unit B;
interface
implementation
uses A;

Which compiles:

  • try interface A, fail need B
  • try interface B, ok!
  • try interface A, ok!
  • try implementation A, ok!
  • try implementation B, ok!

Each unit also has an initialization section (and if it has an initialization section, it could also have a finalization section.) The initialization section is used to initialize the variables of the unit. The finalization sections are used to cleanup. When you use these, its wise not to count on initializations of other units. Just keep them simple and short.

Unit also are namespaces. Considder the following:

unit A;
interface
const foo = 1;

unit B;
interface
const foo = 2;

unit C;
interface
uses A, B;

const
  f1 = foo;
  f2 = A.foo;
  f3 = B.foo;

If an identifier is defined in multiple used units, the last unit possible in the uses list is taken. So f1 = 2. But you can prefix it with the unit (namespace) name to solve this problem.

With the introduction of .net, multi part namespaces are allowed which introduces other nice problems:

unit foo;
interface
type
  rec1 = record
    baz : Boolean;
  end;
var
  bar : rec1;

unit foo.bar;
interface
var
  baz : Integer;

uses
  foo, foo.bar;    
begin
  foo.bar.baz := true;
  foo.bar.baz := 1;
end.  

// 1. Which these lines gives an error and why?
// 2. Does the result change if you write uses foo.bar, foo?

In this case you have a conflict. But that is resolved by giving namespace names higher priority. So the first line fails.

Gamecat