Namespace and Uses

In Oxygene, all Types (and Globals) are contained in a namespace. You can think of a namespace as a longer version of a name, that helps group related types together, and to avoid name ambiguity between types with the same name (but in different namespaces).

A type"s full name is its namespace, followed by a dot, followed by the type's short name. The namespace itself may contain additional dots, to indicated a nested hierarchy of namespaces:

MyCompany.AHelperClass
MyCompany.MyProject.SomeClass

Here, both "MyCompany" and "MyCompany.MyProject" are (separate and distinguished) namespaces. And "AHelperClass" and "SomeClass" are the short names of two classes defined therein.

It is common to use a company or individual's name as the root portion of namespaces for custom code, to (virtually) eliminate the chance of overlap with code written by other people. For example, all RemObjects code uses namespaces starting with "RemObjects."; that is followed by the name of the product, e.g. "RemObjects.Elements.", "RemObjects.DataAbstract.", and so forth.

Declaring A Namespace

In Oxygene every source file starts with the namespace keyword, followed by the name of the namespace that everything else contained in the file be put into (optionally, this name can be omitted, and type will be generated namespace-less. But this is very rarely done, and discouraged).

namespace MyCompany.MyProject;

...

end.

This declaration affects two things:

  1. By default, all types declared in the file will become part of this namespace.
  2. All types from this namespace — no matter where they are defined — will be "in scope" for the file.

What does this mean, exactly? Let's have a closer look.

1. By default, all types declared in the file will become part of this namespace. This means that if we define a type as follows:

namespace MyCompany.MyProject

type
  MyClass = class
    ...
  end;

then the MyClass class will automatically be considered part of the MyCompany.MyProject namespace. Its so-called *full name will this be "MyCompany.MyProject.MyClass". And this full name is how the class can be referred to everywhere.

2. All types from this namespace will be "in scope" for the file. This means that if we add a second (or more) files to our project and also begin it with namespace MyCompany.MyProject, these files will be part of the same namespace, and all types from that namespace will be in scope in all the files (no matter which file they were declared in). As such, we can refer to the above class simply as MyClass — because it is in the same namespace.

One can add as many files to a project as needed and they can all share the same namespace. In most (smallish) projects that only have a single namespace, there is no need to worry about adding namespaces to the uses clause (more on that below), just to access classes from within the project's code base. All types are automatically in scope in all source files (of the same namespace).

Of course, while it is common for small to medium projects to just use a single namespace, it is also common to declare different namespaces across a project in order to better partition parts of the project — for example one could have a MyCompany.MyProject namespace for the bulk of a project, but a MyCompany.MyProject.MySubSystem namespace for a certain sub-system of the project.

Regardless of namespace, all types declared in a project will be available all throughout the project (unless they are marked for unit level visibility only) by their full name, and all types marked as public will also be available outside of the project (i.e. when you are creating a library that will be referenced from other projects).

Code in the MyCompany.MyProject namespace could refer to a type from the sub-system simply by using it's full name:"

var x := new SomeClassFromTheMainNamespace(); // no need to specify the full name
var y := new MyCompany.MyProject.MySubSystem.SubSytemClass();

Uses Clauses

Of course, it would become cumbersome to always refer to types from other namespaces using their full name – especially if the same type, or many types from the sanem namespace(s) are used frequently through-out a source file.

By providing a uses clause with a list of namespaces at the top of the file, these additional namespaces can be brought "into scope" as well, so that anything declared in them can now also be accessed using the short name.

namespace MyCompany.MyProject;

uses
  MyCompany.MyProject.MySubSystem;

...

var y := new SubSytemClass(); // MyCompany.MyProject.MySubSystem is now in scope!

A uses clause can list one or more namespaces (separated by comma). Alternatively where convenient, multiple uses clauses can be provided, each terminated by a semicolon. This is especially helpful when using {$IFDEF}s:

namespace MyCompany.MyProject;

uses
  CoreFoundation,
  Foundation;
  
{$IF MACOS}
uses
  AppKit;
{$ENDIF}
...

Resolving Ambiguities

If more than one namespace in scope declare a type of the same (short) name, using that name will refer the one in the namespace that is most towards the end of the uses clause. Of course you can still use the full type name, to be sure, or to refer to one of the other types of the same name:

namespace MyCompany.MyProject;

uses
  MyCompany.MyProject.MySubSystemA,
  MyCompany.MyProject.MySubSystemB,

...

var y := new SubSytemClass(); // comes from MyCompany.MyProject.MySubSystemB
var z := new MyCompany.MyProject.MySubSystemA.SubSytemClass(); // explicitly use the type from MySubSystemB

WildCards

In addition to listing individual namespaces, the uses clause also allows the asterisk character as a wildcard, to include a namespace and all its sub-namespaces. For example, uses MyCompany.MyProject.* would add MyCompany.MyProject.SubSystemA and all the rest to the scope, including recursive sub-namespaces.

namespace MyCompany.MyProject;

uses
  MyCompany.MyProject.*;

Standard Namespaces

Certain System namespaces will be in scope by default and do not manually need to be listed in the uses clause for their types to be accessible by their short name.

  • The RemObjects.Elements.System namespace contains compiler-intrinsic types, such as Integer, System Functions and other elements, and is always first in scope.

  • On .NET, the System namespace contains many core classes, such as String and Object, and is always second in scope.

  • On Java, the java.lang namespaces contain many core classes, such as String and Object, and are always second in scope.

  • On Cocoa, the rtl.* namespace contains the C runtime library, core types and many core C-based APIs and is always second in scope.

(On Island, all standard types are in the above-mentioned RemObjects.Elements.System)

Project-Wide Default Uses Clauses

In addition, you can specify a list of namespaces be in scope for all files via the "Default Uses Clause" Project Setting. Any namespaces in that list will be in scope before those listed in an individual source file's uses clause (in alphabetical order, with RemObjects.Elements.RTL, of present, last).

The unit Keyword

For backwards compatibility with Delphi, Oxygene allows the unit keyword to be used instead of namespace. Note that even when using that keyword, the following identifier still specifies the namespace for that file, and all the above discussion still applies.

Just as with namespace, the identifier does not have to match or correspond to the file name, and multiple (or even all) files in the project can (and typically will) use the same namespace.

See Also