Next: Operators, Previous: Files, Up: Programming
Users may also define their own data types as structures, along with
user-defined operators, much as in C++. By default, structure members
are public
(may be read and modified anywhere in the code), but may be
optionally declared restricted
(readable anywhere but writeable
only inside the structure where they are defined) or private
(readable and writable only inside the structure). The virtual
structure this
refers to the enclosing structure. Any code at the
top-level scope within the structure is executed on initialization.
The implicit initializer for a structure S
is new S
(which
creates a new anonymous instance of S
).
A null instance of a structure results on assigning it the value
null
.
This implicit initializer can be overwritten with the
operator init()
to allow for a custom initialization of each
instance of S
:
S operator init() { S s=new S; return s; }
Here is a simple example that illustrates the use of structures:
struct S { real a=1; real f(real a) {return a+this.a;} } S s; // Initializes s with new S; write(s.f(2)); // Outputs 3 S operator + (S s1, S s2) { S result; result.a=s1.a+s2.a; return result; } write((s+s).f(0)); // Outputs 2
In the following example, the static function T.T(real x)
is a constructor that initializes and returns a new instance of T
:
struct T { real x; static T T(real x) {T t=new T; t.x=x; return t;} } T a; T b=T.T(1); write(a.x); // Outputs 0 write(b.x); // Outputs 1The name of the constructor need not be identical to the name of the structure; for example, see
triangle.SAS
in geometry.asy
.
Structure assignment does a shallow copy; a deep copy requires writing
an explicit copy()
member. The function bool alias(T,T)
checks to
see if two instances of the structure T
are identical.
The boolean operators ==
and !=
are by default equivalent to
alias
and !alias
respectively, but may be overwritten
for a particular type do a deep comparison.
When a
is defined both as a variable and a type, the qualified
name a.b
refers to the variable instead of the type.
Much like in C++, casting (see Casts) provides for an elegant implementation of structure inheritance, including virtual functions:
struct parent { real x=1; void virtual(int) {write (0);} void f() {virtual(1);} } void write(parent p) {write(p.x);} struct child { parent parent; real y=2; void virtual(int x) {write (x);} parent.virtual=virtual; void f()=parent.f; } parent operator cast(child child) {return child.parent;} parent p; child c; write(c); // Outputs 1; p.f(); // Outputs 0; c.f(); // Outputs 1; write(c.parent.x); // Outputs 1; write(c.y); // Outputs 2;
Further examples of structures are Legend
and picture
in
the Asymptote
base module plain
.