The most important characteristics of objects are:
Objects are variables that need to be initialized from a Class. The most simple object is an instance of type Object. The Object is the fundamental class in EVE, that is why it starts with uppercase.
Initialize an object by using an object literal with initialization values:
# define an object instance globals Object object_name1 = (); //empty object Object object_name2 = (attribute:value, ...);
Notes:An object is a reference to a data structure that is created by using the default constructor. This receive a list of attribute-value pairs: (attribute:value, ...). The default constructor accept a list of parameters, you do not have to specify the constructor name, just the list of parameters.
Initialize an object by using an explicit constructor call.
#define an object instance locals Object object_name; // create a Null object process ** initialize object using Object() constructor object_name := Object(attribute:value, ...); ... return;
Note: One object instance can receive attribute names that do not exist and bind values to them using column ":" symbol. Default constructor will create new attributes automatic and set-up an implicit data type using type inference. However after object is created the structure is locked: no other attributes can be added.
You can create more complex objects by using a class constructor. This start with keyword "class". This makes special subroutine that can create an object. The object name that is going to be created is an implicit output parameter, that is called "self" and that is available without declaring it.
A class constructor start with keyword: "class" and is a block of code similar to a routine. Unlike the routine it does not have a "process" region but it has "create" region instead and it has "remove" region that is also executable.
#class constructor class ClassName(parameters): ** object attributes ... ** object methods ... static ** class attributes ... ** class methods ... create ** call object default constructor self := Object(object_attribute:argument,...); ... remove ** object release region ... return;
Notes: In EVE we consider the class as an object factory. The objects are factory products. They can receive factory support and maintenance. So a class can perform object maintenance after the object was created.
A class can have a single constructor. A constructor can use decision statements based on parameter values to create "object" in different ways based on conditions. This help us to create complex constructors.
... create ** conditional construction if condition then self := Object(some_arguments); else self := Object(other_arguments); end if; return;
A class constructor can have parameters that receive arguments. You can define optional parameters with default values. Constructor receive argument values using a "constructor call". This call is similar to a "routine call". Parameters can be also assigned using a JSON literals.
# define a class with prameters class ClassName(parameters): ** class body .... return; locals ** declare null object of type ClassName ClassName object_name; process ** macking a constructor call object_name := ClassName(param:value,...); ... return;
Class instances are more complex than fundamental objects. Instances can have custom methods and private attributes that a simple object can not have. Any class is by default extending the root class that is the Object class.
Objects: can be declared and initialized in a single statement using a class constructor. Complex objects can be initialized only by using a user define constructor and not by using the default object constructor.
This is how you create a class instance:
objectName := ClassName(arguments);
The object_name from previous example, is the current instance that is created using a class constructor. Under the hood, object are actually created explicit in the create region of the class constructor using this syntax:
Next we use object name "self" that is the implicit object name, reserved by EVE. This is is the result of class constructor. It is similar to the "result" variable used in sub-routines. The self object is created explicit using an assign statement like:
self := SuperClass(arguments);
A class can have object attributes and class attributes. In other languages, these are called properties or fields. They represent actually states of an object. We stick with the term attributes in EVE documentation.
To access object attributes we can use dot notation:
We already know how to instantiate a class and create objects using a class constructor. After you have defined a class, this do not know anything about it's objects. You can not ask the class anything about it's instances.
For a class, you can define static attributes and methods. That's the secret: a class is actually a singleton object. The class is holding the class states. Each attributes defined in the static region belong to the class singleton object.
You can access all static members without instantiation of the class. But you can also access class members using the object qualifier. Both will point to the same class states also called class attributes.
** accessing static attributes ClassName.class_attribute; // using the class name object_name.class_attribute; // using the object name
There is a special class that has name "Object"and represents the "root" class. Each classes grows from Object or from other "base class" forming a "class tree". Like a real tree the class hyerarchy has a single root.
This example define a "Point" class with two parameters. The parameters have default values so they are optional when you create a point. Read the example and the notes to undestend how to use a user defined class constructor.
# define a "Point" class driver point_demo: class Point(Double x = 0, y = 0): Double .x, .y; //public attributes create .x := x; .y := y; return; locals Point: p1, p2; //declare two Null points process ** initialize the points p1 := Point(x:1, y:2); p2 := Point(x:2, y:2); ** use string patterns to print attributes print ("p1 = (a:#n, b:#n)" ? (p1.a,p1.b)); print ("p2 = (a:#n, b:#n)" ? (p2.a,p2.b)); return;
p1 = (a:1, b:1) p2 = (a:2, b:2)
We can use two comparison operators with objects: "is" and "==". First operator "is" will compare the object location or object type. If the objects have same location they represent the same object. Second operator: "==" compare object class and object attributes. There are complementar operators "is not" and "!=". That can be used to create oposite logical arguments.
In next examples we use a primitive type: Integer, that is actually a class
#object comparison demo driver object_compare: locals Integer o = n = 1; // context variables process ** equal values and types expect o == n; expect not (o != n); ** not the same location expect not (o is n); expect o is not n; ** alter one value n := 2; ** equal values and types expect o != n; expect not (o == n); return;
EVE has support for inheritance. You can specify a superclass using symbol "<:" that is equivalent of keyword: "extend" used in Java. Using this symbol makes a class that has all attributes and methods of the super-class.
# define a class with prameters class ClassName(parameters) <: base_class: ** class members ... create ** call base class constructor self := base_class(object_attribute:argument,...); ... remove ** object release region ... return;
Read next: Data Processing