Declarations
Value structs
Declare value types that are copied on every assignment, pass and return, with derived equality and explicit mutating methods.
since 0.1.0-alpha.1linuxwindowswasm
Description
A struct is a value type. Where a class variable holds a reference to a shared object, a struct
variable holds the value itself. A struct is copied every time it is bound to a variable, passed to
a function, returned, or stored into an array or another object, and a copy has no connection to the
original. Structs have no identity.
struct Point {
int x; int y;
int dot() => x * x + y * y;
mutating void translate(int dx, int dy) { x = x + dx; y = y + dy; }
}
A method that changes this must be marked mutating; a plain method that assigns a field is a
compile error. Constructors and set accessors are mutating by definition. Choose a struct for plain
data such as coordinates and rows, and a class for entities with identity. Arrays of structs can be
stored densely, which makes them compact and fast to scan; see lang.columnar-arrays.
Structs are copied
struct Point {
int x;
int y;
int dot() => x * x + y * y;
mutating void translate(int dx, int dy) { x = x + dx; y = y + dy; }
}
Point a = Point(1, 2);
Point b = a;
b.translate(10, 10);
console.writeln(a.x);
console.writeln(b.x);
console.writeln(a.dot());
void bump(Point p) { p.translate(100, 100); }
bump(a);
console.writeln(a.x);
Array<Point> ps = [Point(1, 1), Point(2, 2)];
Point first = ps.at(0);
first.x = 99;
console.writeln(ps.at(0).x);
console.writeln(a == Point(1, 2));
console.writeln(a != b);
1
11
5
1
1
true
true
b is a copy: translating it leaves a untouched. The function bump changes only its own copy, and
changing first leaves the array's element alone.
Rules
- A struct is copied on bind, pass, return and store. The copy is deep for nested structs; a field that holds a reference (a class instance) copies the reference, so the copy and the original share that object.
- A struct is final: it cannot inherit from a class or another struct and nothing can inherit from it. It may implement interfaces.
- A method that writes a field of
thismust be declaredmutating. Calling amutatingmethod through aconstbinding is a compile error. - Constructors and
setaccessors may write fields without themutatingkeyword. - A struct has a derived
==and!=that compares the fields one by one. Fields of struct type are compared field by field in turn, and a field that holds a class instance is compared by identity, so two different objects with equal contents make the structs unequal. - Derived equality is available only when every field is comparable. A struct that has an array or
map field has no derived
==; definebool (==)(Type other)to compare such a struct. - A struct compares by value when used as a
Mapkey or in aSet.
Examples
The copy shares referenced objects, and equality compares references by identity:
Nested structs, shared references, and equality
class Box { int n = 0; }
struct Point { int x; int y; }
struct Line { Point from; Box box; string name; }
Line a = Line(Point(0, 0), Box(), "a");
Line b = a;
b.from.x = 50;
b.box.n = 7;
console.writeln(a.from.x);
console.writeln(b.from.x);
console.writeln(a.box.n);
console.writeln(a == Line(Point(0, 0), Box(), "a"));
console.writeln(a == Line(Point(0, 0), a.box, "a"));
0
50
7
false
true
from is a nested struct, so b has its own copy of it; box is a reference, so both lines share
one Box. The first comparison is false because it builds a new Box; the second reuses a.box.
A struct can implement an interface:
A struct implementing an interface
interface IShow { string show(); }
struct Tag : IShow {
string text;
string show() => "<" + text + ">";
}
IShow s = Tag("hi");
console.writeln(s.show());
<hi>
Structs cannot be inherited from or inherit implementation:
Structs are final
struct P { int x; }
class Q : P { } // error: cannot inherit from struct 'P'; value types are final
class B { int x; }
struct S : B { } // error: struct 'S' cannot inherit implementation
struct M { int x; void bad() { x = 1; } } // error: mark the method `mutating`
See also
- Classes — Declare reference types with fields, methods, constructors and accessors, with generics and inheritance from one or more base classes.
- Fields — Declare the data a class or struct holds, with optional initializers, and how a field without an initializer gets its default value.
- Interfaces — Declare the members a class must provide, including fields, and let any class satisfy them by declaring those members.
- Columnar storage of struct arrays — How native builds lay out an array of simple structs column by column, when that applies, and how to turn it off.