Structs
Structs inherit from Value so they are allocated on the stack and passed by value: when passed to methods, returned from methods or assigned to variables, a copy of the value is actually passed (while classes inherit from , are allocated on the heap and passed by reference).
Therefore structs are mostly useful for immutable data types and/or stateless wrappers of other types, usually for performance reasons to avoid lots of small memory allocations when passing small copies might be more efficient (for more details, see the performance guide).
Mutable structs are still allowed, but you should be careful when writing code involving mutability if you want to avoid surprises that are described below.
Notice that the chained calls of plus
return the expected result, but only the first call to it modifies the variable counter
, as the second call operates on the copy of the struct passed to it from the first call, and this copy is discarded after the expression is executed.
You should also be careful when working on mutable types inside of the struct:
What happens with the strukt
here:
Array
is passed by reference, so the reference to["str"]
is stored in the property ofstrukt
- the array referenced by
array
is modified (element inside it is added) byobject.array << "foo"
- this is also reflected in the original
strukt
as it holds reference to the same array object.array = ["new"]
replaces the reference in the copy ofstrukt
with the reference to the new array- returns the reference to this new array and its content is printed
- the reference to this new array was held only in the copy of
strukt
, but not in the original, so that’s why the originalstrukt
only retained the result of the first statement, but not of the other two statements
Inheritance
- A struct implicitly inherits from Struct, which inherits from . A class implicitly inherits from Reference.
The second point has a reason to it: a struct has a very well defined memory layout. For example, the above Point
struct occupies 8 bytes. If you have an array of points the points are embedded inside the array’s buffer:
If is inherited, an array of such type should also account for the fact that other types can be inside it, so the size of each element should grow to accommodate that. That is certainly unexpected. So, non-abstract structs can’t be inherited from. Abstract structs, on the other hand, will have descendants, so it is expected that an array of them will account for the possibility of having multiple types inside it.
A struct can also include modules and can be generic, just like a class.