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 read-only when referenced outside the structure, but may be
optionally declared public (read-write) or private (read
and write allowed 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.
A default initializer for a structure S can be defined by
creating a function S operator init(). This can be used to
initialize each instance of S with new S (which creates
a new anonymous instance of S).
struct S {
public real a=1;
real f(real a) {return a+this.a;}
}
S operator init() {return new S;}
S s; // Initializes s with S operator init();
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 operator init() {return new T;}
T a;
T b=T.T(1);
write(a.x); // Outputs 0
write(b.x); // Outputs 1
The 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;
public void virtual(int) {write (0);}
void f() {virtual(1);}
}
parent operator init() {return new parent;}
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;}
child operator init() {return new child;}
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.