Classes#

What is a Class#

The concept of a class is taken mostly from C++ here, although notably simplified down. By declaring a class, you declare a template of data to be used repeatedly in creating objects, along with some functions associated with that data.

While the order of the parts within a class mostly doesn’t matter to the compiler, you will generally see classes organized in the same general order:[1]

  1. Data: The variables that make up the class. Can contain arrays, too.
    • While technically not ‘required’, a class without data has little purpose.

    • Declared via normal variable declarations. Cannot have initializers.

  2. Constructor(s): A function or functions to create the class.
    • Not required- leaving it out is the same as declaring an empty constructor function.

    • The constructor is declared as a function with the exact same name as the class and no return type.

    • The parameters may be whatever you like.

  3. Destructor: A function to destroy the class.
    • Not required- leaving it out is better for the compiler than declaring an empty destructor function.

    • A destructor is declared as a function named ~ followed by the exact same name as the class and no return type.

    • The destructor takes no parameters.

    • The destructor is automatically called when the object is destroyed by the engine.

      Changed in version 3.0: The destructor can no longer manually be triggered with delete. This is no longer necessary due to the refcounting + garbage collector.

  4. Member Functions: Any other functions you like.
    • All class functions (without the static modifier) have a local variable named this, which is a pointer to the object itself.

Note

The order the data is declared in is relevant to existing save files, for any objects saved to the save file. As such, changing the order can break existing save files (in the same way that declaring any new global variable can)

Allocating Objects#

To create an instance of an object, you call its constructor function using the new keyword[2]. A pointer to the object, whose type is the class itself, will be returned.

Limits

A maximum of 214747 objects can exist at a time, from all (non-internal) classes combined. If this many objects exist at once, the new call will fail, returning NULL.

Object Cleanup#

Full Explainer

The program keeps track of all the references to each object, and automatically deletes any object when the last reference to it is lost (calling the destructor, if defined).

There is additionally a garbage collector, which is capable of cleaning up cyclical references (the situation in which the only reference left to two different objects, is inside the other, thus they ‘keep each other alive’ for the reference counting)

Tip

OwnObject grants a single “reference” to the object to whichever entity the function is giving ownership to. If that entity dies, it causes the ownership reference to be ‘lost’.

Tip

GlobalObject marks an object as “global”. Objects that are “global” will be saved to the save file, and cannot be destroyed.

Calling OwnObject marks the object as no longer “global”.

Static Functions#

Declaring a function inside a class with the static modifier makes the function a static part of the class, rather than a part of each object. Static functions have a few differences from normal member functions:

  • No this pointer (meaning no access to any data members from the class)

  • Called similarly to functions inside namespaces, except that a . is used after the class name, rather than the scope-resolution operator ::

Effectively, they are functions whose only thing to do with the class, is that they are called using the class’s name. One possible use of such functions would be to create ‘named constructors’ for different purposes[3].

Array Data Members#

Declaring an array as a data member of an object creates a special type of array. Notably, you cannot re-assign a different pointer to such an array, and OwnArray/DestroyArray have no effect on these arrays.

These arrays are effectively ‘owned’ by the object, and are destroyed when the object is destroyed. They are also saved to the save file with the object, if the object is global.

Note that this only applies to actual array declarations- declarations of variables with array types that are not array declarations still act as normal.

Not Yet Implemented

Currently, attempting to re-assign a pointer to such an array does not give a compiler error- it simply has no effect. This will likely become a compiler error in the future.

Examples#