Namespace and Uses
In Oxygene, all Types are contained in a namespace. You cna 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 indicateb a nested hierarchy of namespaces:
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 startung with "
RemObjects."; that is followed by the name of the prodduct, e.g. "
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 thisn is very rarely done, and discouraged).
namespace MyCompany.MyProject; ... end.
This declaration affects two things:
- By default, all types declared in the file will become part of this namespace.
- 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;
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) file 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 syb-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();
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!
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 ful 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
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.*;
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.
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
Project-Wide Default Uses Clauses
In addition, you can specify a list of namespaces be in scopr 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).
- Global Access (