class

Purpose The class statement is used to define a class and load it into the run-time class memory or to redefine an existing class.
Format class {class name} : {comma-separated list of parent classes} {
   construct {
      {scope specifier}:
         {descendant nodes}
   }
   {scope specifier}:
      {method type} {method name}({parm type} {parm pass type}{parm name},... ) {
         {method statements}
      };
   {scope specifier}:
      {member var type} {member var name} = {initial value};
      .
      .
      .
      
      <{member arr type} {member arr name and size} = {initial values};
      .
      .
      .
      
};

{class name} the name of the class being defined and loaded into run-time class memory.
{comma-separated list of parent classes} the comma-separated list of the names of the parent classes from which this class inherits properties and behaviour-- use "" if the class does not inherit from any other.
{scope specifier} defines the accessibility of the embedded items: can be public, protected or private.
{descendant nodes} the actual XML renderings of contained objects that are to be automatically instantiated whenever an object of this class is instantiated.
{method name} the name of a method that implements a behaviour in this class.
{method type} the datatype of the returned value of the method: use void if there is no returned value.
{parm name} the name of a parameter that is passed into the method.
{parm type} the datatype of a parameter that is passed into the method.
{parm pass type} the type of parameter passing: * means pass by reference; if it is omitted then it means pass by value.
{method statements} the statements to be executed when the method is invoked.
{member var type} the datatype of a member variable of the class.
{member var name} the name of the member variable.
{initial value} the initial value of the member variable that it is set to when an object of the class is instantiated.
{member arr type} the datatype of a member array of the class.
{member arr name and size} the name and number of elements in the member array.
{initial values} the comma-separated list of initial values of the member array elements bounded by curly braces.

construct
The construct clause is refered to as the structural constructor. Its purpose is to define the set of contained objects/nodes for the class. Each of these nodes may inherit from other classes by means of the class attribute. The object that is instantiated from the class which owns the construct clause will contain nodes as specified in the clause.

Inheritance
Single inheritance is implemented in a class by writing the name of only one class in the inherit attribute of the class statement. Multiple inheritance is achieved by writing more than one class name in the inherit attribute. A node defined in the construct clause specifies single or multiple inheritance by writing the name(s) of the class(es) in the node's class attribute. An instance of the class defined in the class statement implements single or multiple inheritance by writing the name(s) of the class(es) it inherits from in the class attribute of the node statement that instantiated it. Please note that if the inherit or class attributes are empty, the node will inherit only from the Node abstract class.

Function/Method Invocation
Methods are invoked via the dot notation. Methods that take parameters will have these passed to them within the {parameters} section shown below.
{object name}.{ancestral class}::{method name}({parameters});

In the above statement the {object name} is the name of the object owning the method and the :: is the special token of the method invocation that specifies which class will handle the method call. The {ancestral class} specifies the name of the class to handle the method call. The {method name} is the name of the method to be invoked and the {parameters} are the required parameters of the method. In normal circumstances you will omit the :: and the {ancestral class} and let the Superx++ run-time engine resolve the appropriate class to handle the method. Method resolution is done by finding the first class that implements a method in the inherit or class attributes. From there resolution moves up the inheritance hierarchy if the method was not yet found.


Function/Method Return Values
Methods can return a value back to the calling portion of a program. This is why the methods have datatypes. The value is returned back to the caller via the return statement. When the return statement executes it passes back the return value to the caller and terminates the method. The return statement can also be found within the main part of a Superx++ program in which case the program terminates. There is no value passed back to the caller of the Superx++ program.
return {return value};

In the above statement the {return value} is the value that is to be passed back to the caller. The method then terminates at this point.


Function/Method Over-riding
Function over-riding is implemented when a class inherits from another class and implements another version of a method found in the ancestral class. It is possible to invoke the method found in the ancestral class (at any level-- not just the parent/super class) by means of the  :: token using the following format:
this.{ancestral class}::{method name}({parameters});

In the above statement the  :: is the special token of the method call that specifies which class will handle it. The {ancestral class} specifies the name of the class to handle the method call. The {method name} is the name of the method to be invoked and the {parameters} are the required parameters of the method.


Class Redefinition
Class redefinition is implemented by the execution of a subsequent class statement which contains the same declared name as a previously defined class. All objects that are instantiated using the definition found in the original class statement will still exist after the class redefinition. They will be modified in the following manner:
Their methods will be the ones defined in the redefining class statement

However, the formerly instantiated objects will remain the same in every other regard, that is:
1) Their properties will remain the same
2) The set of contained objects they possess will remain the same

Newly instantiated objects after the redefinition will be defined completely after the redefined form. They will therefore differ from their older relatives as follows:
1) They will have different properties
2) They will contain a different set of objects


Condition Class Definition (Polymorphic Class Definition)
Conditional class definition is implemented by the execution of a class statement within a conditional statement such as an if or a switch statement. Here is an example:
if (rev = "new") {
   class XPlant {
      construct {
         public:
         <Age />
      }
      public:
         string Species;
   };
} else {
   class XPlant : XTree {
      construct {
         public:
         <Age />
         <Size />
      }
      public:
         string Species;
   };
}

In this example above we have two different definitions of the same class, XPlant. If the rev parameter is set to new then the first class statement in the if statement executes and defines the XPlant class in one way. If the rev parameter is not set to new then the second class statement in the if statement executes and defines the XPlant class the other way. An obvious advantage to this polymorphic definition of the class is in the case of versioning. If you have two versions of a program, then you can use the old class definition for the old version and the new class definition for the new version. The possibilities are limited to your imagination with what you can do with polymorphic class definition.


Method Classes

It is possible to define classes within methods of other classes. This has the benefit of creating temporary types that are disposed of automatically once they are used. So you create the class within your method and use it there. Then once the method terminates the class is automatically deleted from class memory. Here is an example:
class XCalc{
   public:
      int SpecialCalc(int op1, int op2) {
            class XTemp {
               public:
                  int Do(int a1, int a2) {
                        return a1 + a2;
                  };
            };
            node(XTemp) TempObj;
            return TempObj.Do(a1 = op1, a2 = op2);
      };
};
node(XCalc) MyCalc;
xout("The calculation yields " + MyCalc.SpecialCalc(op1 = 200, op2 = 300));

In this example above we have a class XCalc which has a method SpecialCalc. SpecialCalc contains a class XTemp which performs the real calculation. In this case, it is simple addition but more complex logic could be included. The benefit is that the XTemp class with its special logic is deleted from class memory once the method that defines it terminates.


Examples
Example #1

classXPlant {
   construct{
      protected:
         <Size units="feet">50</Size>
   }
   public:
      int GetSize() {
            return Size;
      };
};

node(XPlant) AppleTree;
xout("The size of the AppleTree is " + AppleTree.GetSize());

The class XPlant is defined above with a single contained node, Size, which contains an attribute, units, with the value, feet. Size is a protected object within the class so no code outside the class can access it. We therefore have a method to access it called GetSize which takes no parameters and whose return value is an int. The node statement is not part of the class definition. It is the instruction that performs the instantiation of the object, AppleTree, which is an object of class, XPlant. We then use the <eval> statement to invoke the GetSize method and we use the <xout> statement to send the returned value to the output stream. The result is that the following text is sent to the output stream: The size of the AppleTree is 50.

Example #2 classXPlant {
   construct {
      protected:
         <Size units="feet">50</Size>
   }
   public:
      int GetSize() {
            return Size;
      };
      string FruitBearing= "yes";
      int ProfitPerYear[3]= {200,150,127};
};

node(XPlant) AppleTree;
xout("The size of the AppleTree is " + AppleTree.GetSize());
xout("\r\nDoes the AppleTree bear fruit? " + AppleTree.FruitBearing);
xout("\r\nWhat was the profit 3 years ago? " + ProfitPerYear[0]);
xout("\r\nWhat was the profit 2 years ago? " + ProfitPerYear[1]);
xout("\r\nWhat was the profit 1 years ago? " + ProfitPerYear[2]);

The class XPlant is the same as in Example #1 above with some changes. In this example, the member variable and the member array are invoked. The net result is that the following text is sent to the output stream on separate lines:
The size of the AppleTree is 50
Does the AppleTree bear fruit? yes
What was the profit 3 years ago? 200
What was the profit 2 years ago? 150
What was the profit 1 year ago? 127