Local Fields
The field statement is used to declare and optionally initialize a new field in the class that is private to the current scope (e.g. a method).
It works very much like a local variable declaration with var, except that it defines a field, and the value stored in it will persist between calls to the current scope. The Field will be available for all code below its declaration, up until the end of the current scope – that is either to the end of the current method, if the field is declared on that level, or to the end of the block Statement that includes the declaration.
Local fields in Oxygene are what some other languages, such as C, might somewhat confusingly refer to as "static variables".
In its simplest form, a local field declaration starts with the keyword field, followed by a new unique name for the variable, a colon (:), and the type.
field i: Integer;
Optionally, the declaration can be followed by an initial value for the variable, assigned via the := operator. Variable declarations without initializer will be initialized to the default value of their type.
field i: Integer := 5;
If an initial value is provided, the field will be initialized the very first time it's declaration is hit. The right-hand side of the expression will not be re-evaluated on subsequent runs, and the value of the field will not reset.
Type Inference
When an initializer is provided and a concrete type can be inferred from it, the type name can optionally be omitted. This is referred to as type inference.
field i := 5;
It is important to note that – unlike in scripting languages such as JavaScript – the field will still be strongly typed, in the above case to be an Integer. Omitting the type name is merely a convenience (and sometimes a necessity, when using Anonymous Types which have no name), but that does not mean that the field is untyped.
Oxygene will use the type of the expression to the right of the := operator to infer the type, if possible. For numeric literals, the inferred type will be the smallest integer that can fit the literal, but no smaller than a 32-bit signed integer.
Static Fields
By default, local fields declared in a regular method are tracked per instance — just like a Field declaration on class level would. This means, each instance of the class gets its own copy of the field – but each call to a method on the same instance will use the same field.
Optionally, local fields can also be declared as static using the class prefix or the static directive. Static fields will be tracked as a single field per class, meaning one value is shared across all instances of the class.
class field i := 5; // same i for every instance
Of course, fields declared inside a static method, or a method of a static class will always be static, by default.
Declaring Multiple Fields in one Statement
Multiple fields of the same type can be declared in one statement by separating them with a comma. When using this option, no initializer may be provided, as it would be ambiguous whether the initialization would apply to all variables or only to the last one.
field a, b: Integer;
Storage Modifiers (Cocoa)
On Cocoa only, the type name of a field declaration can be amended with the weak, unretained or strong Storage Modifier keywords, with strong being the default.
field lValue: weak String;
To specify a Storage Modifier, the type cannot be inferred, but must be explicitly specified. Inferred types will always be considered strong.
Modifiers
Similar to type members, the following modifiers are allowed on local variables:
pinned— can be applied to pointer and class reference variables on the .NET platform to indicate that the target object will be pinned to a fixed location and may not be moved by the Garbage Collector while the field is alive (applicable on platforms that use GC, namely .NET and Java).readonly— indicates that the field may not be altered after its declaration. For obvious reasons, this only makes sense for fields that have an initializer.static— indicates that the field is static (see above).
field i := 5; readonly;
field a := new Customer; pinned;