Properties are a type of class member. A property consists
of a name together with a **get** and **set** accessor. Either
the get accessor or the set accessor may be defined (or both accessors may be defined).
The name of a property can be used in expressions and assigments
like a normal variable but the get and set accessors are invoked
when reading or writing the variable. The general form of a property
is shown below.

name { get { // get accessor code } set { // set accessor code } }

The **name**
names the property. Any use of the property results in a call to the appropriate
accessor. The set accessor automatically recieves a parameter called **value**
that contains the value being assigned to the property.

Properties can be used to assign another name to a variable. For example, the class complex has two fields a and b (the real and imaginary components). It is possible to assign other names to these fields, as the next example shows.

// property_a - properties - real and imaginary using system space property_a { class complex { a b complex() { a = 0.0 b = 0.0} complex(aset) { a = aset b = 0.0 } complex(aset bset) { a = aset b = bset } real { get {return a} set { a = value } } imaginary { get { return b } set { b = value } } operator string() { return (string)a + " + i * " + (string)b } } property_a() { c = complex() c.real = 10.0 c.imaginary = 20.0 cout << c << "\n" } }

The output of the program is as follows.

10 + i * 20

In this case, the properties real and imaginary merely provide other names for the fields a and b. In the function, values are assigned to the properties real and imaginary and the set accessors for these properties are called. This updates the fields a and b.

It would have been possible for the properties real and imaginary only to provide a get accessor. This would deliver read-only access to the fields a and b. Likewise, only the set accessor could have been defined, delivering write-only access to the fields a and b. Often properties that are associated with a field are used to restrict the range of values that can be assigned to the field.

Not all properties have to be directly associated with a field as for the previous example. Properties are often quantities obtained from a computation. Extending complex, we obtain a number of new properties, which are not associated directly with a field. Added are properties for the modulus and argument of a complex number. These properties are the results of computations and are thus read-only properties.

// property_b - properties - modulus and argument using system space property_b { class complex { a b complex() { a = 0.0 b = 0.0} complex(aset) { a = aset b = 0.0 } complex(aset bset) { a = aset b = bset } real { get {return a} set { a = value } } imaginary { get { return b } set { b = value } } operator string() { return (string)a + " + i * " + (string)b } norm { get { return a * a + b * b } } modulus { get { n = norm return n.square_root() } } argument { get { if (a == 0.0 && b == 0.0) return 0 else { d = b / a return d.arc_tan() } } } } property_b() { c = complex() c.real = 10.0 c.imaginary = 20.0 cout << c << "\n" m = c.modulus s = "modulus == " + (string)m cout << s << "\n" a = c.argument s = "argument == " + (string)a cout << s << "\n" } }

The output of the program is shown below.

10 + i * 20 modulus == 22.36067977499789805051477742381393909454345703125 argument == 1.10714871779409040897235172451473772525787353515625

The modulus of a complex number is the length of a vector whose base is the origin and whose tip is the complex number (plotted on a 2d coordinate system). Pythagoras' theorem is used to obtain the formula for the modulus of a complex number. The argument of a complex number is the angle it makes with the x-axis. The arctan function is sufficient to calculate the argument.