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:
- 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;
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.
The visibility of constructors is governed by which Visibility Section of the containing type the method is declared in.
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
By default, constructors in Oxygene do not participate in
override, even when overriding constructors from a base class.
The usual modifiers can be used when designing classes to be used with, please refer to that topic for more details.
unsafemarks a constructor as using unsafe code, such as direct pointer manipulation on .NET. (available and required on .NET only).
emptymarks the constructor as containing no code, and it cannot have an implementation body.
partialmarks the constructor for special behavior inside a , as discussed in that topic.
externalmarks a constructor as being a declaration for a method or function that is linked in from an external library. Usually used in combination with , and not commonly used. No implementation body may be provided.