GOLD Classes

In this page, the basis of the GOLD language are presented. The current page is an addition to the general description, focusing our attention on how classes are constructed in GOLD language and how they are used.

In Rulex Studio code event, any persistent modification we want to execute on the current situation needs to be performed on the underlying View instance. Therefore, a in-depth knowledge about GOLD classes and instances is mandatory to exploit the maximum potential of the component.

Classes offer a way to bundle data and functionality together. The creation of a new class generates a new type of object, allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining its state. Class instances can also have methods (functions defined inside class definition) for modifying its state.

Compared with other programming languages, GOLD class mechanism is inherited by the one of Python classes. As Python classes, also GOLD classes provide all the standard features of Object Oriented Programming: the class inheritance mechanism allows multiple base classes, a derived class can override any methods of its base class or classes, and a method can call the method of a base class with the same name. Instances can contain arbitrary amounts and kinds of data. Moreover, even GOLD classes are created at runtime, and can be modified further after creation.

Like in C++, even in GOLD classes, most built-in operators with special syntax (arithmetic operators, subscripting etc.) can be redefined for class instances.


GOLD Class Definition

The simplest form of class definition looks like this:

class ClassName:
   <statement-1>
   *
   *
   *
   <statement-N>

Class definitions, as function definitions must be executed before they have any effect. Statements contained in a class definition are usually of two different kinds:

  • Assignment operation (as i = 1000): this operation creates a new field inside the Class prototype which is then replicated in any subsequent instantiation.

  • Function definition (as def f(a, b)): this operation creates a new method inside the Class prototype which is then replicated in any subsequent instantiation.

Note

At any moment you can access GOLD class prototype by referring to the global variable @<class-name>. This global variable acts as a normal class instance but any modification on it will affect all the next instantiation.

Class instantiation is written as a function notation x = ClassName() and creates a new class copy of the current state of the Class prototype with separate fields and methods. Class instantiation can then be customized by defining into the Class prototype a __init__ method.

def __init__(self):
   self.myfield = []

In this way calling the same instantiation as before will create in the instance (and not in the prototype) a new field named myfield to which is assigned an empty vector.

Note

The internal word self is used as in Python to indicate the new instance within its method.

Of course, we can pass to the __init__ method more arguments for greater flexibility.

def __init__(self, name, surname):
   self.completename = surname + " " + name

In this case, Class instantiation should contain the value of the arguments to be used in the function call itself (as x = ClassName(Alighieri, Dante))


Field and Methods

Once an instance is defined, you can access its internal fields and methods by using the . operator.

class Test:
   a = 5

   def sum(b):
      return a+b

ins = Test()
print("field = %, sum = %", ins.a, ins.sum(3)) # field = 5, sum = 8

The . operator for method call also define which variable will be used as value of self keyword in its resolution.

Note

Definition of self parameter is maintained also after assignment operation of instance method.

ins = Test()
op = ins.sum
print("sum = %", op(3)) # sum = 8

Class Inheritance

Of course, a language feature would not be worthy of the name “class” without supporting inheritance. The syntax for a derived class definition looks like this:

class DerivedClassName(BaseClassName):
   <statement-1>
   *
   *
   *
   <statement-N>

Execution of a derived class definition proceeds the same as for a base class. When the class object is constructed, the base class is remembered. This is used for resolving field references: if a requested field is not found in the class, the search proceeds to look in the base class. This rule is applied recursively if the base class itself is derived from some other class.

There’s nothing special about instantiation of derived classes: DerivedClassName() creates a new instance of the class. Method references are resolved as follows: the corresponding class method is searched, descending the chain of base classes, if necessary, and the method reference is valid if this yields a function object.

Derived classes may override methods of their base classes. Because methods have no special privileges when calling other methods of the same class, a method of a base class that calls another method defined in the same base class may end up calling a method of a derived class that overrides it. An overriding method in a derived class may in fact want to extend rather than simply replace the base class method of the same name. There is a simple way to call the base class method directly: just call BaseClassName.methodname(self, arguments). This is occasionally useful to clients as well. (Note that this only works if the base class prototype is accessible in the scope of the derived class prototype.)

Of course, GOLD supports a form of multiple inheritance as well. A class definition with multiple base classes looks like this:

class DerivedClassName(Base1, Base2, Base3):
   <statement-1>
   *
   *
   *
   <statement-N>

In this case, the search for fields and methods inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy. Thus, if a field is not found in DerivedClassName, it is searched for in Base1, then (recursively) in the base classes of Base1, and if it was not found there, it was searched for in Base2, and so on.


Operator Override

In GOLD language, it is possible to redefine in GOLD classes the base behavior of general operators listed here. For each operator a reserved method is assigned in the class definition. If present, any time the operator symbol is resolved by GOLD parser the associated class method is called instead of the standard base operation.

Here’s a list of the overriding reserved functions and the corresponding operators. (Left function means the operator is override if a class instance is present on the left of the considered operator, right function vice-versa; for unary operator only left function is considered):

Operator

Left function

Right function

>=

__ge__

__rge__

<=

__le__

__rle__

==

__eq__

__req__

!=

__ne__

__rne__

is

__is__

__ris__

is not or not is

__nis__

__rnis__

and

__and__

__rand__

or

__or__

__ror__

not

__not__

in or isin

__contains__

+

__sum__

__rsum__

-

__sub__

__rsub__

*

__mul__

__rmul__

/

__div__

__rdiv__

%

__mod__

__rmod__

^

__pow__

__rpow__

=

__assign__

[] indexing operation

__sbraket__

Note

If you want to use the instance as a function (therefore calling it as explained in this section), you need to define a method with the reserved node __exec__