Inheritance is a useful feature that Aria Templates makes easy to manage. You can reuse and extend an existing class quite simply.
Just declare your child class as inherited from a parent one by using the
$extends keyword. Like in Java programming language, multiple inheritance is not available. A single class can only inherit from one parent class.
When your class inherit an another one, it then inherit from all properties, statics, constructor and destructor.
In Aria Templates, any object inherit from
aria.core.JsObject. Thus, your class automatically has access to several helpers coming from this parent root object, like for example logging methods:
$logError(), and many more.
An interface is a description of a set of methods, properties and events, but not containing implementation code at all. Classes (or implementations) can decide to implement one or more interfaces, and therefore specifically provide the code for these methods, properties and events.
Interfaces are generally used in programming languages as a way to define a clear contract between a functionality provider and its client(s), and hide the implementation details, in order to easily be able to change them.
Programming with interfaces can make code more elegant, more decoupled, more extensible and more easily unit testable.
Interfaces in Aria Templates support the following features:
An interface can be defined through Aria.interfaceDefinition, as shown in the following sample:
An interface definition contains the following parts:
$classpath(mandatory) - the classpath is a unique identifier of the interface, just like in Java, and in Aria Templates classes. It corresponds to the package name + the interface name.
$extends(optional) - the classpath of another interface declared with Aria.interfaceDefinition, which will be the super interface of this one.
- If an interface extends another interface, all interface members declared in the super interface, including methods, properties and events, are automatically inherited as if they were declared in this interface.
- Unlike in Java, multiple interface inheritance is not possible in Aria Templates. However, a class can implement several interfaces if needed.
$interface(mandatory) - This section contains empty methods and empty properties that must be implemented in classes that implement the interface.
- Interface members can be:
- A function: can be declared with either an empty function, or the string
"Function", or a json structure with the
$typeproperty containing "Function". With this last syntax, it is possible to specify that the function is asynchronous by setting the
$callbackParamproperty. This property must contain the index of the argument of the function which contains the callback. Declaring asynchronous functions in an interface is especially useful when using interceptors.
- An object or array: declared as shown in the above example. Note that the reference to the object or the array must stay the same in the object from its construction until it is disposed. This is because interface wrappers never update the references to the properties.
- An interface must be declared with a json structure with the
$typeproperty containing "Interface", and the
$classpathproperty containing the classpath of the interface. When creating the interface wrapper containing such a member, the corresponding member from the whole object must implement the interface specified here and only its interface wrapper will be published in the interface wrapper.
- A function: can be declared with either an empty function, or the string
$events(optional) - set of event definitions, using the same syntax as in Aria Templates classes.
Once an interface has been defined through Aria.interfaceDefinition, it can be used in class definitions as shown in the following example:
- When declaring that a class is implementing an interface through the
$implementskeyword, the class must contain in its prototype (or in the prototype of one of its super-classes) all the methods declared in the interface, otherwise, an error is logged and the class load fails.
- There is no check for the presence in the class of the properties (objects or arrays) defined in the interface, as it cannot be checked at class load time (properties are usually available only when creating an instance of a class).
- Events declared in the interface are automatically imported in the class definition. They must not be declared again in the class definition.
If an object is an instance of a class which implements an interface, it is possible to retrieve a wrapper on that object that only contains the members (methods, properties and events) declared in the interface and prevents access to the remaining members of the object. This is useful to be sure that only members of the interface are actually used, so that the code using the interface is really decoupled from the interface implementation.
To get an instance of an interface wrapper, simply call the
$interface method on the object, with the classpath of the interface to get. For example, with the
ariadoc.snippets.core.classes.Fruit class declared above:
Interfaces can declare events in the
$events part of the interface definition. Events declared in the interface are automatically imported in the class definition. They must not be declared again in the class definition.
If an interface declares events, its wrapper object will automatically contain the following additional methods:
These methods are wrappers on the methods from aria.core.JsObject, with the following specific aspects:
- when registering a listener on a wrapper object, when the event is raised, the
srcproperty of the event object will contain the wrapper object and not the whole object
$unregisterListenersfrom a wrapper object cannot unregister events registered with another wrapper object or with the complete object, it can only unregister events registered with the same wrapper object
$unregisterListenersfrom the complete object can unregister events registered with any wrapper object
The first thing you have to understand as far as dependencies are concerned is their type. Aria Templates can handles 2 different kinds of dependencies:
- Static dependencies
- You can express them using the
$dependencieskeyword in your classDefinition. This keyword takes as argument an array that contains all the different classpaths that you know your class is strongly dependent on.
- This is more or less like the import declaration in Java.
- Dynamic dependencies
- This kind of dependency is to be used when you know that your class will only needs it under certain circumstance. Thus, you can use the helper method Aria.load on the Aria singleton object.
- This helper takes also as argument a JSON configuration object, in which you can specify an array of classpaths to be loaded. Once all the classes are loaded, a callback is used to trigger code execution.
Natively, all Aria Templates objects are Observable. Because of the implicit inheritance from the original root object (
aria.core.JsObject) on all of your classes, Aria Templates gives you the ability to declare and listen to events. Any class could listen to events that could be raised by any other class.
The emitter class declares the events it is able to fire using the
$events keyword property on the classDefinition. This property is basically a list of event names along with their description and potential custom properties.
Then, to raise an event, you simply have to use
$raiseEvent(eventName) method. (Which again is there implicitly because of aria.core.JsObject inheritance)
On the other hand, a listener class should just simply declares that it is listening using the