Declarations
Accessors
Replace how a field is read or written with get and set, and define computed values and indexers.
since 0.1.0-alpha.1linuxwindowswasm
Description
An accessor changes what reading or writing a name does. get defines a read, set a write:
get value() => value; // read view over the 'value' slot
set value(int v) value = v * 2; // write view
get ([])(int i) => cells[i]; // indexer (computed accessor)
set ([])(int i, int v) cells[i] = v; // the value being stored is the last parameter
A parameterless accessor is a view over a field of the same name. Inside the accessor body the
name refers to the raw field, so get value() => value + 100 reads the stored number and does not
call itself. A get can also be declared with no field of that name, which makes it a computed,
read-only property.
An accessor with parameters is a computed accessor and needs no backing field. The index accessor
([]) is the common case: a[i] calls the get ([]) accessor of a's class and a[i] = v calls
the set ([]) accessor, which mutates the object in place.
Views, computed properties and an indexer
class Gauge {
int value = 1;
get value() => value + 100;
set value(int v) value = v * 2;
get doubled() => value * 2;
}
Gauge g = Gauge();
console.writeln(g.value);
g.value = 5;
console.writeln(g.value);
console.writeln(g.doubled);
class Grid {
Array<int> cells;
new Grid() { cells = [0, 0, 0, 0]; }
get ([])(int i) => cells[i];
set ([])(int i, int v) cells[i] = v;
}
Grid grid = Grid();
grid[2] = 7;
grid[0] += 5;
console.writeln(grid[2]);
console.writeln(grid[0]);
console.writeln(grid[1]);
101
110
220
7
5
0
Setting g.value = 5 stores 10 in the field, because the set accessor doubles it; reading it
back adds 100. g.doubled is computed from value through its accessor, so it is (10 + 100) * 2.
Rules
get name() => exprandset name(T v) statementdefine the read and the write ofname.- Inside an accessor for
name, the bare namenameis the raw field: the accessor does not call itself. Other names go through their own accessors. - A parameterized accessor is computed and needs no backing field. The value being assigned is the
last parameter of a
set. - The index accessors are written
get ([])(params)andset ([])(params, value); the selector has no spaces inside the parentheses.a[i] += vreads throughgetand writes throughset. - If a name has only a
getaccessor, writes go to the field directly (the stored value is changed but later reads still pass throughget). If agethas no field behind it, a write to the name is silently ignored. - If a name has only a
setaccessor, reads return the field directly. - An accessor is bound to the field of its name in the class that declares it: in a combined
object, a same-named field that another base contributes (a
distinctone, say) is read and written directly, never through this accessor. - A
setaccessor in a struct is mutating without being marked. Asetaccessor may not be declared over aconstorreadonlyfield.
Examples
A write to a name that has only a computed get is ignored:
A get without a field
class C {
int stored = 4;
get twice() => stored * 2;
}
C c = C();
c.twice = 3;
console.writeln(c.twice);
c.stored = 10;
console.writeln(c.twice);
8
20
An accessor on a struct:
A set accessor on a struct
struct Temp {
int raw;
get celsius() => raw;
set celsius(int v) raw = v * 2;
}
Temp t = Temp(1);
t.celsius = 5;
console.writeln(t.raw);
10
See also
- Operator declarations — Define operators on a class or struct by declaring a member with a symbolic selector such as (+), (==) or ([]).
- Fields — Declare the data a class or struct holds, with optional initializers, and how a field without an initializer gets its default value.
- Value structs — Declare value types that are copied on every assignment, pass and return, with derived equality and explicit mutating methods.