Class
Principle
Danger
Important: The classes system of the framework is not related to the classes defined by EcmaScript 6 !
The framework is build on the Object-oriented programming (OOP
) paradigm, and so are the applications build with the framework. It supports classes
, which may contain properties
, constructor
, methods
and additional keywords to help in building the component. A class is declared into a file. A file must contain only one class.
import $Class from "@Class";
/**
* A simple class example
*
* @name MyClass
* @class
* @extends Class
*
* @property {type} myProperty ...
*/
export default $Class.declare("MyClass", {
traits: [],
statics: /** @lends MyClass */ {},
properties: {
myProperty: null
},
constructor: function(properties) {},
methods: /** @lends MyClass.prototype */ {
publicMethod: function() {},
_protectedOrAbstractMethod: function() {},
__privateMethod: function() {}
}
});
A class is declared with the $SuperClass.declare(classPath, classDefinition)
method, where
$SuperClass
is a reference to theSuperClass
(don’t forget to import it) from which the class inherits - Every object inherits fromClass
classPath
is the path to the classclassDefinition
a map that contains the definition of the class
A typical class declaration may contain the following object-oriented features:
constructor
: the class constructor, called when you create a new instance of the class,statics
: statics methods and properties of the class (and not of the instance of the class),methods
: class methods; protected, abstract and private by using naming conventions,properties
: a map of class properties,traits
: add new behaviours to the class
Usage
Constructor
The constructor of class is provided as a function declaration with the reserved keyword constructor
.
All constructor have the first argument which is an object containing properties. Here is an example:
var MyClass = $Class.declare("MyClass", {
properties: {
"message": "choubidou"
},
constructor : function(properties) {
// The first argument of all constructor of Class's is the properties of the class
console.log(properties.message); // choubidou
console.log(this.message); // choubidou
}
});
new MyClass({message:"hello !"}); // hello !
Inheritance
In order to derive the current class from another class, you need to declare the class from the superclass.
Caution
Super-constructor(s) are always called before the Class constructor. There is no way to skip the call(s) of super-constructor(s).
var SuperClass = $Class.declare("SuperClass", {
constructor: function() {
console.log("I'm the super class !");
}
});
var MyClass = SuperClass.declare("MyClass", {
constructor: function() {
console.log("I'm a cool class !");
}
});
new MyClass(); // I'm the super class !
// I'm a cool class
All classes inherit from Class
.
Statics
You can declare static members in a class with the reserved keyword statics
:
$Class.declare("Circle", {
statics: /** @lends Circle */ {
PI:3.14, // Define a static constant
getPerimeter: function(radius) { // Define a static method
return 2 * radius * this.PI; // here, 'this' points to the class
}
}
});
Circle.getPerimeter(10); // 2*10*Circle.PI
Caution
- static members are carried by the class object and not by its prototype,
- to access a static member you need to access it from the class object,
- a static member can reference another static member through
this
object which in this case point to the class object and not the current instance, - static members are inherited; if the
RedCircle
class inherits from theCircle
class:- you can call
RedCircle.getPerimeter()
- you can refine statics:
Circle.declare("RedCircle", {superclass:Circle,statics:{PI:3.1416}});
- you can call
- an instance of a class can refer to its own statics using
this.statics
(in it’smethods
)
Methods
A method is a function that will be added to the Class prototype (i.e. instance method). By convention, protected/abstract methods are prefixed with an underscore and private ones with two underscores.
var MyClass = $Class.declare("MyClass", {
methods: /** @lends MyClass.prototype */ {
publicMethod: function() {},
/**
* @protected
*/
_protectedMethod: function() {},
/**
* @abstract
*/
_abstractMethod: function() { throw new Error("you must implement _abstractMethod"); },
/**
* @private
*/
__privateMethod: function() {}
}
});
var myClass1 = new MyClass();
myClass1.publicMethod();
// FOLLOWING IS FORBIDDEN !!
myClass1._protectedMethod(); // While it is possible, don't call protected methods from instance
myClass1._abstractMethod(); // While it is possible, don't call abstract methods from instance
myClass1.__privateMethod(); // While it is possible, don't call private methods from instance
Properties
Properties of the class must be defined into the properties
keyword.
/**
* @property {string} state - the current state
*/
var MyClass = $Class.declare("MyClass", {
properties: {
state: "CREATED"
},
constructor: function(properties) {
console.log("state="+this.state);
}
});
new MyClass(); // state=CREATED
new MyClass({state:READY}); // state=READY
var myClass = new MyClass();
myClass.state = "READY";
Caution
- properties are inherited from the superclass
- in the constructor, the first arg is the properties object that contains resolved properties
- you must document the property in the class definition (
@property
) - modern ide will recognize the property in your code
Methods inheritance and superclass
When methods are overridden, we often want to keep the execution of the original code. You can call the parent function.
Caution
There is no support of the super
keyword: use $SuperClass.prototype.<methodName>.apply(this, arguments)
.
Example:
var Media = $Class.declare( "Media", {
methods: {
setProps: function(props) {
this.url = props.url;
}
}
});
var Movie = $Media.declare( "Movie", {
methods: {
setProps: function(props) {
Media.prototype.setProps.apply(this, arguments);
this.title = props.title;
}
}
});
Singletons
The singleton pattern is a design pattern that restricts the instantiation of a class to one object. A method getInstance()
is added to such a singleton class. The singleton is supported using classes annotations.
/**
* @singleton
*/
var MySingleton = $Class.declare("MySingleton",
{
/**
* @private
*/
constructor: function(properties) {
console.log("Instance initialized !");
if (this.once === undefined) { this.once = 0; }
this.once ++;
},
methods: {
getOnce: function() {
console.log(this.once);
}
}
});
MySingleton.getInstance().getOnce(); // Instance initialized !
// 1
MySingleton.getInstance().getOnce(); // 1
MySingleton.getInstance().getOnce(); // 1
// FORBIDDEN
var badWayToGetSingleton = new MySingleton();
As you can not call the constructor of a singleton directly, you pass the properties
to the constructor of a singleton with your profile.