The Language
Oxygene is a powerful general purpose programming language, designed to let developers create all imaginable kinds of projects on a wide variety of platforms.
To achieve this, it provides a combination of language features that ease the development processes — from basic Object Oriented language concepts found in most modern languages (such as the concept of classes with methods, properties and events) to sophisticated specialized language features that enable and ease specific development tasks (such as creating safe, multi-threaded applications) — many of them unique to Oxygene.
All of the provided features are based on the foundation of Object Pascal and stay true to the language design paradigms that make Pascal great, readable and discoverable.
Like all the Elements languages, Oxygene comes with support for four distinct Platforms: .NET, Cocoa (the platform behind macOS and iOS), Android, Java, Windows, Linux and WebAssembly.
Object-Oriented Background
At heart, Oxygene is a purely object oriented language, meaning that all code is contained in Classes and other Types, which can expose Members such as Methods, Properties and Events.
On the Cocoa and Island platforms, additional allowances are made for accessing non-object-oriented platform APIs, like the C runtime functions.
Keywords
Object Pascal, just like Pascal before it, is easily readable by both humans and computers. This is by design, and is accomplished through the use of English words instead of symbols to define most of the language. For example, blocks of code are delimited with the begin
and end
keywords in sharp contrast to the C family of languages (which includes Elements' three other languages, C#, Swift and Java), which use the curly braces {
& }
to accomplish the same task.
This extends through all aspects of the language, aiming for a "read as plain english" approach for features, where feasible. For example, where C#, Swift and Java use a cryptic ?
to mark nullability, Oxygene uses the nullable
keyword, and where C-style languages use &
and |
, Oxygene relies on readable operator names such as and
and or
.
Case & Naming Conventions
The language itself, is not case sensitive, but it is case preserving, and Oxygene – unlike older Pascal dialects – is case-preserving, and will emit warnings (and suggest automatic fixes) if identifier case is used inconsistently. However two identifiers that only differ in case are not permissable.
By convention, reserved words (Keywords) in Pascal are written in lowercase, but the compiler will permit and recognize uppercase and mixed case keywords, as well.
In older Pascal dialects, like Turbo Pascal and Delphi, it was convention to prefix class names with a T
; this is no longer the case with Oxygene (although Oxygene does preserve the convention of prefixing interface types with I
to distinguish them from regular classes).
Aside from that, there are no formal naming or case conventions in Oxygene. Typically, the naming and case follows the conventions of the underlying framework – which is a mixture of "PascalCase" and "camelCase", depending on the platform. For cross-platform or non-platform-specific code, "PascalCase" is recommended.
Structured Programming
One of the things that differentiated Pascal when it was introduced is that it was designed to be a structured programming language. This translates into two things: The first is that it was designed to support complex data structures like lists and records. The second is that it supports various control structures like for
, case
, while
, repeat
, etc., as well as procedures & functions, without the need to rely on goto
or jump
like unstructured languages (in fact, Oxygene drops the goto
keyword that is available in legacy Pascal altogether).
Classes
Classes defined in Oxygene belong to a class hierarchy rooted in a base
object called Object
(which maps to System.Object
in .NET, java.Object
in Java and Foundation.NSObject
in Cocoa). Each class declaration either explicitly specifies an ancestor class, or will implicitly descend from Object
.
Classes inherit all members from their ancestor classes and are thus said to extend that class – commonly by adding additional members or providing overridden implementations of select members defined in the ancestors.
Classes can be marked as abstract
to indicate that they need to be extended in order to be instantiated and used. They can also be marked as sealed
to indicate that they cannot be extended further.
Methods and Other Class Members
Methods define the execution flow of applications written in Oxygene. Each method consists of a list of Statements that get executed in turn when a method is called. Statement types include loops, conditional statements, logical and mathematical expressions or calculations, or calls to other members in the same or different classes.
Pascal originally differentiated between procedures and functions (the latter being a procedure that returned a result) by using different identifiers, and early Object Pascal implementations carried this legacy over when introducing object-orientation, although this terminology no longer seemed accurate. The Oxygene language no longer differentiates the two by keyword and consistently uses the method
keyword for, well, methods (although the procedure
and function
keywords remain available as compatibility option).
Properties provide controlled access to data contained within a class instance, and can be read/write, read-only or (in rare cases) write-only. Events allow objects to retain references to call-back methods on other objects that they can call, when necessary.
While methods and properties (next to private fields or instance variables) are the two core kinds of members that make up classes, other more advanced member kinds are supported as well, such as Events, Invariants or Nested Types.
Class members can be declared at different visibility levels to control how they can be accessed from outside the class they are in. The three most important levels include private
visibility, which restricts access to the class itself; protected
visibility, which allows access only from descendants of the class; and public
, which allows any code in the project to access the member (but several more fine-grained visibility levels are available as well).
With Oxygene being a truly object oriented language, all code you write will generally be contained in classes (or encoded in other types), with no "global" functions or other elements.
Other Types
Classes are the core of any object oriented program, but they are complemented by a range of other kinds of types that enrich the language:
- Interfaces are abstract types that define a set of shared methods, events or properties that can be implemented by one or more (otherwise unrelated) classes. Classes that implement the same interface can be accessed in identical ways by code that might otherwise be unaware of the concrete class types. This makes it easy to write code that can act on "similar" classes, without those classes having to share a common ancestor. Many developers consider Interfaces to be a cleaner replacement for multiple inheritance, which Oxygene intentionally does not support.
- Records behave similar to classes, but are stack-based rather than heap-based. They can also contain fields, methods and properties, like classes do.
- Enums are simple types that provide a collection of named values.
- Standard types include Simple Types such as integers, floats and strings, as well as more complex types such as arrays, sets and Modified Types.
Advanced Concepts
The Oxygene language contains numerous advanced language concepts, many of which are common to most modern languages, some of which are inspired by other less mainstream languages and yet others which are entirely unique to Oxygene.
- Class Contracts allow optional code to be included with class definitions and method implementations to enforce class consistency. These contracts can be enforced at runtime, leading to more precise and timely error reporting when constraints are not met as expected.
- Sequences and Query Expressions are deeply integrated into the language to work with various types of lists of objects, iterate them, and perform advanced queries (such as filtering, sorting or combining) on them.
- Several language constructs for Parallelism are integrated into the language to make it easy to write multi-threaded code that scales well from single-CPU to multi-core computers. These include Parallel Loops, Future Types, Asynchronous Expressions and more.
- Duck Typing and the Dynamic type provide more weakly typed language constructs akin to more dynamic languages such as Objective-C or JavaScript, where needed.
- Generics provide for classes to be customizable to work with different types without having to write separate implementations. For example, a generic list class can be implemented (or indeed provided by the underlying frameworks) and then be instantiated to be a list of a very specific concrete type.
File Structure
The Code File Structure topic explains how an Oxygene .pas
file is structured and how the types and code are laid out, within.
Cross-Platform Compatibility
The language aims at being ~99% identical and compatible between the platforms, but there are a few subtle differences owed to the underlying platforms, covered in the Platform Differences Overview.
With very few minor exceptions dictated by the underlying runtimes, the Oxygene language is designed to be virtually the same across all three supported development environments: .NET, Cocoa and Java.
This means that the language syntax is 99% identical on all three platforms, and that a lot of the code you write can be shared between the platforms (as long as it does not use platform-specific APIs, of course), and that all the language knowledge and experience you build up using Oxygene can be applied to all platforms. Using the same language also makes it easier and more intuitive to work on apps for the different platforms, without having to "switch gears" between – say – C#, Java and Objective-C all the time.
And the open source Elements RTL base library makes sharing code between projects across all three runtimes even easier.