Namespaces vs. Unit Names

Th the very top, Oxygene and Delphi source files start very similarly, but even though they may look almost the same, there are some key semantical differences, and there is enhanced flexibility in how Namespaces in Oxygene let you structure your code.

Units in Delphi

In Delphi, every unit starts with the keyword unit (or program/package) followed by an identifier that gives that unit a name. That name can be used elsewhere in code to make the types fork this unit available, by using the name in the uses clause elsewhere.

Right after that (and after the interface keyword, usually comes the aforementioned uses clause, which lists all the other units that you want to refer from the code that follows:

unit MyThirdUnit;

interface

uses
  MyFirstUnit, MySecondUnit;

A separate uses clause can be provided in the implementation section, of course.

The unit system has some strict limitations:

  • Each unit – that is, every single source file in your Delphi project, must have a unique name
  • The unit's name must match that of the file on disk (minus the file extension).
  • Two units cannot use themselves circularly, in the interface section.

The last is the most critical limitation. It means you cannot for example have two types, in two separate units, that both reference each other in their public interface. The only way to achive such a thing is to out both classes into the same file.

Namespaces in Oxygene

Oxygene does not really have a concept of units, but this standard Delphi structure still compiles and works in Oxygene. Why? Because Oxygene partitions code into Namespaces, and if each source file in your project sets its own name, that simply means that each source file creates its own namespace.

And while Oxygene prefers.suggests the namespace keyword to start a new fine, it also allows the unit keyword for backward compatibility.

As a result, the standard unit structure you know from Delphi works ok.

But, Oxygene code can escape from the strict shackles outlined below and gain much flexibility, by embracing the concept of namespaces:

  1. in Oxygene, the name given at the top of each file does not have to be be unique, and it must not match the file on disk. Several files in your project can specify the same name, and they will all contribute to the same namespace. In fact, it is very common to only have a single namespace for an entire small project (or a section of a larger project), or only a handfull of themselves.
  2. All types in the same namespace can see each other directly, without a uses clause – even if they live in separate files.
  3. Types from other namespaces can be accessed by adding their namespace to the uses clause.
  4. There is no restriction on "circular references" – files for one namespace can use another and vice versa, without limits.

This opens up many flexibilities for structuring your code across files and namespaces. In fact, it is very common in Oxygene to give each class (especially non-trivial ones) their own source file, for clarity. (You can even split a very large class across several files, with Partial Types, but that is another topic).

namespace MyOnlyNamespace;

interface

uses
  Some.External.Comonent.Library;

Namespaces can contain dotted separators to indicate a hierarchy of namespaces and sub-namespaces (e.g. MyProject.SubSystem1, MyProject.SubSystem2), but that is purely cosmetic and informational.

See Also