Constructors

Constructors define the code that is run when a new instance of a class is constructed.

They are very much like methods in that they are declared with optional parameters and a body of code, but they cannot be called directly. Instead, the compiler will automatically execute the proper constructor (or list of constructors) when the new operator is used to instantiate a copy of the class.

A class can have multiple constructors that are overloaded by the number and/or type of parameters.

type
  MyClass = public class
  private
    val: Integer;
  public
    constructor;
    constructor(a: Integer);
  end;

constructor MyClass;
begin
  val := 0;
end;

constructor MyClass(a: Integer);
begin
  val := a;
end;
...

var x := new MyClass();   // calls the first constructor
var y := new MyClass(15); // calls the second constructor

Each constructor must call into either a different constructor of the same class or a constructor of the base class in order to fully complete the construction of the class.

If no explicit call is written, the compiler will automatically call the constructor of the base class, either one that matches the exact set of parameters or the parameterless one (if the base class has no parameterless constructor, compilation will fail and an explicit call needs to be coded).

You can explicitly call a different constructor by using the constructor keyword as a statement:

constructor MyClass;
begin
  inherited constructor(); // call parameterless constructor of base class
  fValueForA := 0;
end;

constructor MyClass(a: Integer);
begin
  fValueForA := a;
  constructor(); // call parameterless constructor of same class
end;

constructor MyClass(a: Integer; b: Double);
begin
  fValueForB := b;
  constructor(a); // call other constructor of base class
end;
...

var x := new MyClass();   // calls the first constructor
var y := new MyClass(15); // calls the second constructor

Multi-part Constructor Names

In order to fit in well with the API conventions on the Cocoa platform, Oxygene has support for multi-part constructor names.

Just as with multi-part method names, multi-part constructor names are essentially the ability for a constructor name to be split into separate parts, with each parameter getting a distinct name. This is "required" on the Cocoa platform because all the platform's APIs follow this convention, and we wanted Oxygene to be able to both consume and implement methods alongside those conventions without resorting to awkward attributes or other adornments, and to feel at home on the Cocoa platform.

For cross-platform completeness, multi-part constructor names are now supported on all platforms, and considered a regular feature of the Oxygene language (and also compatible with RemObjects C# and Swift). We encourage you to use and embrace them, as they greatly help to make code more readable and understandable.

A multi-part constructor has parameter parts for each part, both when being declared:

method constructor withSomething(aFirstParameter: Integer) andSomethingElse(aSecondParameter: Integer);

...and when being called:

var x := new MyClass withSomething(5) andSomethingElse(10);

On Cocoa, single-part constructors map to init methods, while multi-part constructors map to initWith* methods. You can use either constructor syntax (recommended) or method syntax with the right naming conventions to define Cocoa class constructors.

Extended Constructor Calls

Very often the first task after creating a class instance is to initialize some of its properties that are not set by a constructor. For example:

var b := new Button();
b.Title := 'Click me!';

Oxygene allows you to add named parameters after the normal constructor parameters in order to fill properties on the constructed object. These are in the form of name := value pairs. Thus, the code above can be written like this:

var b := new Button(Title := 'Click me!');

This extended syntax is only supported for constructors, and the named parameters must be placed after any of the regular constructor parameters.

Field and Property Initialization

Oxygene allows fields and properties to be initialized inline. Any such initialization technically will happen as part of the construction of the class, and the compiler takes care of making this transparent.

Fields and properties are normally initialized before any inherited constructor is called, except if the field initializer:

  • uses self directly
  • accesses fields or properties of the ancestor class
  • calls any method of the current class or the ancestor class

Consider the following code:

type
  Foo = class
  private
    Field1: string := 'hello';
    Field2: &Type := self.GetType();
  public
    constructor;
  end;

implementation

constructor Foo;
begin
  // Field1 will be initialized here
  Console.WriteLine(Field1);
  Console.WriteLine(Field2.Name); // error
  inherited constructor;
  // Field2 will be initialized here
  Console.WriteLine(Field2.Name);
end;

Because Field2 uses self in its initialization, it cannot be initialized until after the base constructor was run. Field1 doesn't rely on self, so it will be initialized at the beginning and is accessible from the start.

Static fields are initialized from an implicit class constructor.

Visibility

The visibility of constructors is governed by which Visibility Section of the containing type the method is declared in.

Static/Class Constructors

By default, constructors are applicable to individual instances of a class – that means they work on the instance being constructed.

A single parameterless static constructor can be provided by prefixing the constructor declaration with the class keyword. This static constructor will automatically be called once (and exactly once) before the first instance of the class is created or the first static member of the class is accessed.

class constructor; // static constructor

Regardless of what section it is declared in, the static constructor will always have private visibility.

Virtuality

By default, constructors in Oxygene do not participate in Polymorphism, unless Class References are used – which is rare. As such, you will not generally declare constructors as virtual or override, even when overriding constructors from a base class.

The usual modifiers can be used when designing classes to be used with Class References, please refer to that topic for more details.

Other Modifiers

  • unsafe marks a constructor as using unsafe code, such as direct pointer manipulation on .NET. (available and required on .NET only).
  • empty marks the constructor as containing no code, and it cannot have an implementation body.
  • partial marks the constructor for special behavior inside a Partial Type, as discussed in that topic.
  • external marks a constructor as being a declaration for a method or function that is linked in from an external library. Usually used in combination with [DllImport], and not commonly used. No implementation body may be provided.