EXPLAINERS Javascript Inheritance

1. Introduction

The UIZE JavaScript Framework implements a system for class inheritance that makes subclassing and object-oriented programming possible in JavaScript.

2. It's Easy

Subclassing is very easy in the UIZE JavaScript Framework. Creating a fresh subclass is as simple as the following statement...

var MySubclass = MySuperclass.subclass ();

3. Where It's Implemented

The power of classes built using the UIZE JavaScript Framework is derived from the Uize.Class base class.

All classes inherit directly - or indirectly - from this class. While the Uize.Class module is not tiny, the core of the inheritance mechanism itself is quite tiny. What makes the Uize.Class module larger is that it provides not only an inheritance mechanism, but also a JavaScript Event System and a Set-get Properties system.

4. Fleshing Out a Subclass

Each class that you create using the framework inherits the subclass static method, so you can easily make further subclasses of them.

EXAMPLE

var MyClass = Uize.Class.subclass (); // create a class
MyClass.prototype.foo = 'bar';        // create an instance property for the class

var MySubclass = MyClass.subclass (); // subclass the class
mySubclassInstance = new MySubclass;  // create an instance of the subclass

alert (mySubclassInstance.foo);       // alert the subclass instance's foo property

In this example, MyClass is a plain vanilla subclass of the Uize.Class base class. The property foo is assigned on its prototype and is shared by all instances. Now, a subclass of MyClass is created, by the name of MySubclass. An instance of MySubclass is created, and the value of its foo property is alerted. Unsurprisingly, what shows up in the alert dialog is the text "bar". Naturally, meaningful classes are a little more complex than this, but this demonstrates the basics.

The Uize.Class base class provides a mechanism for inheriting instance methods and properties assigned on a superclass' prototype, static methods and properties assigned on the superclass (unless they are registered as non-inheritable statics), and set-get properties registered on the superclass using the registerProperties static method. The inheritance system that is implemented in the Uize.Class base class overcomes some of the weaknesses of a superficial prototype-based approach to inheritance, but we'll get into that a little bit later.

Once you have a subclass, you can modify it by assigning values on its prototype object, adding static methods or properties to the subclass, and registering set-get properties or overriding the initial values of inherited set-get properties.

4.1. Adding Instance Methods and Properties

Adding instance methods and properties to a subclass involves assigning properties on the subclass' prototype object.

EXAMPLE

var MyClass = Uize.Class.subclass ();               // create a class
MyClass.prototype.myInstanceProperty = 'value';     // create an instance property
MyClass.prototype.myInstanceMethod = function () {  // create an instance method
  // do stuff
};

In the UIZE JavaScript Framework, instance methods and properties added to the prototype object of a class are copied to the prototype object of a subclass when creating that subclass. After a subclass is created, modifying the prototype object of its superclass has no effect on that subclass.

4.2. Adding Static Methods and Properties

Adding instance methods and properties to a subclass involves assigning properties on the subclass' prototype object.

EXAMPLE

var MyClass = Uize.Class.subclass ();   // create a class
MyClass.myStaticProperty = 'value';     // create a static property
MyClass.myStaticMethod = function () {  // create a static method
  // do stuff
};

IMPORTANT

In the UIZE JavaScript Framework, static methods and properties assigned on a class are copied to a subclass when creating that subclass (unless they are registered as non-inheritable statics). After a subclass is created, modifying the static methods and properties of the superclass has no effect on that subclass.

4.3. Adding Set-get Properties

You can register one or more set-get properties for a subclass, using the MyClass.registerProperties static method that is inherited from the Uize.Class base class.

EXAMPLE

var MyClass = Uize.Class.subclass ();  // create a class
MyClass.registerProperties ({          // register one or more set-get properties
  _mySetGetProperty:{
    name:'mySetGetProperty',
    onChange:function () {
      // code to handle a change in the property's value
    },
    value:'initialValue'
  }
});

4.3.1. Inheriting Set-get Properties

Set-get properties registered for a class are inherited when creating a subclass.

EXAMPLE

var MyClass = Uize.Class.subclass ();  // create a class
MyClass.registerProperties ({          // register the "foo" set-get property
  _foo:{
    name:'foo',
    onChange:function () {
      // code to handle a change in foo's value
    },
    value:'initial value for foo'
  }
});

var MySubclass = MyClass.subclass (); // create a subclass
MySubclass.registerProperties ({      // register the "bar" set-get property
  _bar:{
    name:'bar',
    onChange:function () {
      // code to handle a change in bar's value
    },
    value:'initial value for bar'
  }
});

After the above code has executed, the class MySubclass will have the two set-get properties foo and bar.

5. Overriding a Superclass

5.1. Overriding Instance Methods and Properties

Overriding instance methods and properties of a superclass is easy. It's just a matter of re-assigning.

EXAMPLE

var MyClass = Uize.Class.subclass ();      // create a class
MyClass.prototype.foo = function () {      // create an instance method
  alert ('bar');
};

var MySubclass = MyClass.subclass ();      // subclass the class
MySubclass.prototype.foo = function () {   // override inherited instance method
  alert ('foo');
  MyClass.prototype.foo.call (this);      // call foo method on superclass
};

myClassInstance = new MyClass;             // create an instance of the class
myClassInstance.foo ();                    // call foo method on instance of class

mySubclassInstance = new MySubclass;       // create an instance of the subclass
mySubclassInstance.foo ();                 // call foo method on instance of subclass

In this example, the foo instance method of the subclass has been overrided so that it first alerts the text "foo" and then calls the foo method implementation from the superclass and alerts the text "bar".

Typically, the code that implements the methods of a subclass is near (or in the same scope as) the code that creates the subclass, so the subclass knows its superclass. When you start to digging into subclass modules, you will encounter this reference to the superclass in the form of the _superclass variable (named such by convention).

5.2. Overriding Static Methods and Properties

Overriding static methods and properties of a superclass is easy. It's just a matter of re-assigning.

EXAMPLE

var MyClass = Uize.Class.subclass ();      // create a class
MyClass.myStaticMethod = function () {     // create a static method
  alert ('foo');
};

var MySubclass = MyClass.subclass ();      // subclass the class
MySubclass.myStaticMethod = function () {  // override inherited static method
  alert ('bar');
};

myClass.myStaticMethod ();                 // call myStaticMethod on MyClass
mySubclass.myStaticMethod ();              // call myStaticMethod on MySubclass

In this example, MySubclass is a subclass of MyClass, and both classes have a static method myStaticMethod. By subclassing MyClass, MySubclass inherits the implementation of myStaticMethod from MyClass. Re-assigning the myStaticMethod property of MySubclass overrides the inherited implementation without affecting MyClass. So, calling myStaticMethod on MyClass will product the text "foo" in an alert dialog, while calling myStaticMethod on MySubclass will product the text "bar" in an alert dialog.

5.2.1. Calling a Subclass Version of a Static Method

One may implement a class in such a way that a static method is intended to be overrided by a subclass. And in such cases, one may also wish the superclass' implementation to be guaranteed to always use the subclass' version of the static method.

Calling a subclass' version of a static method can be done in two ways, depending on whether the code is in the implementation for an instance method or for a static method of the superclass.

5.2.1.1. The Instance Method Case

Within an instance method's implementation, one can use the Class instance property to reference the actual class of the instance - even in the superclass' code - as in...

MyClass.prototype.myInstanceMethod = function () {
  this.Class.myStaticMethod (); // call myStaticMethod static method on subclass
};

Now, in the case of an instance of MyClass, the myStaticMethod static method will be called on MyClass. However, in the case of an instance of MySubclass (that is a subclass of MyClass), the myStaticMethod static method will be called on MySubclass, even though the myInstanceMethod instance method is implemented by MyClass. If MySubclass didn't override the implementation inherited from MyClass, then there will be no difference in the outcome.

Let's take a look at an example...

EXAMPLE

MyClass = Uize.Class.subclass ();          // create a class
MyClass.myStaticMethod = function () {     // create a static method
  alert ('MyClass');
};
MyClass.myInstanceMethod = function () {   // create an instance method
  this.Class.myStaticMethod ();
};

MySubclass = MyClass.subclass ();          // subclass the class
MySubclass.myStaticMethod = function () {  // override inherited static method
  alert ('MySubclass');
};

var _mySubclassInstance = new MySubclass;  // create instance of MySubclass
mySubclassInstance.myInstanceMethod ();    // call myInstanceMethod

In this example, MyClass implements the static method MyClass.myStaticMethod. Now, MySubclass overrides the implementation of myStaticMethod inherited from MyClass. The implementation of myInstanceMethod (inherited from MyClass) uses the Class property to get a reference to the actual class of an instance on which the method is being called. So, when this method is called on the instance of MySubclass named mySubclassInstance, the overrided form of myStaticMethod (implemented by MySubclass) is called, resulting in the text "MySubclass" being displayed in the alert dialog - not the text "MyClass".

5.2.1.2. The Static Method Case

Within a static method's implementation, one can use the this keyword to reference the actual class - even in the superclass' code - as in...

MyClass.myStaticMethod = function () {
  this.myOtherStaticMethod ();
};

Let's take a look at an example...

EXAMPLE

MyClass = Uize.Class.subclass ();               // create a class
MyClass.myStaticMethod = function () {          // create a static method
  this.myOtherStaticMethod ();
};
MyClass.myOtherStaticMethod = function () {     // create another static method
  alert ('MyClass');
};

MySubclass = MyClass.subclass ();               // subclass the class
MySubclass.myOtherStaticMethod = function () {  // override inherited static method
  alert ('MySubclass');
};

MySubclass.myStaticMethod ();                   // call inherited static method

In this example, MyClass implements the two static methods MyClass.myStaticMethod and MyClass.myOtherStaticMethod. The implementation of MyClass.myStaticMethod wants to always call the subclass' version of myOtherStaticMethod. So, instead of calling it as MyClass.myOtherStaticMethod (), it calls it as this.myOtherStaticMethod (). If myStaticMethod is called on MyClass, then this will be a reference to MyClass. However, if myStaticMethod is called on MySubclass, then this will be a reference to MySubclass. Consequently, using this guarantees that the subclass' version will be called. In this example, MySubclass overrides the implementation of myOtherStaticMethod inherited from MyClass, so the statement MySubclass.myStaticMethod () will result in the text "MySubclass" being displayed in the alert dialog - not the text "MyClass".

5.3. Overriding Set-get Property Values

The initial value for a set-get property inherited from a superclass can be overrided by calling the MyClass.set static method that is inherited from the Uize.Class base class.

The initial value for a set-get property is registered by specifying the value property in the profile for the set-get property, as follows...

EXAMPLE

var MyClass = Uize.Class.subclass ();  // create a class
MyClass.registerProperties ({          // register the foo set-get property
  _foo:{
    name:'foo',
    onChange:function () {
      // code to handle a change in foo's value
    },
    value:'bar'
  }
});

var _myClassInstance = new MyClass;    // create instance of MyClass
alert (_myClassInstance.get ('foo'));  // alert value of foo set-get property

In the above example, the text "bar" will be displayed in the alert dialog.

Now, the initial value for the foo set-get property inherited from MyClass can be overrided in a subclass, as follows...

EXAMPLE

var MyClass = Uize.Class.subclass ();      // create a class
MyClass.registerProperties ({              // register the foo set-get property
  _foo:{
    name:'foo',
    onChange:function () {
      // code to handle a change in foo's value
    },
    value:'bar'
  }
});

var MySubclass = MyClass.subclass ();      // subclass the class
MySubclass.set ({foo:'NOT BAR'});          // override initial value for foo

var _mySubclassInstance = new MySubclass;  // create instance of MySubclass
alert (_mySubclassInstance.get ('foo'));   // alert value of foo set-get property

In this example, we have now created a subclass of MyClass named MySubclass. The new subclass inherits the foo set-get property, along with its initial value of 'bar' that is registered in MyClass. The MySubclass.set static method is then used to change the initial value of this set-get property to 'NOT BAR'. Now, the fresh instance of MySubclass that is created, named _mySubclassInstance, will have the initial value 'NOT BAR' for its foo set-get property, and the alert dialog will display this text.

6. Private vs. Public

By convention, private methods and properties - both instance and static - are distinguished from public methods and properties by prefixing their names with an underscore.

EXAMPLE

_classPrototype.myPublicInstanceMethod = function () {    // public instance method
  // do stuff
};
_class.myPublicStaticMethod = function () {               // public static method
  // do stuff
};

_classPrototype._myPrivateInstanceMethod = function () {  // private instance method
  // do stuff
};
_class._myPrivateStaticMethod = function () {             // private static method
  // do stuff
};

Technically, such private methods and properties are not thoroughly private and can be accessed as public methods or properties. However, because their names will be changed by the Scruncher when the code is scrunched to minimize its size, one cannot reliably access these methods and properties. This is a kind of "soft privacy".

IMPORTANT

When creating subclasses, it is important not to access methods or properties defined in the superclass with private names. The code will work when it is unscrunched, but there is no guarantee what your subclass will be accessing when all the code is scrunched.

6.1. Private and Public References

Sometimes, for size optimization, it can be helpful to assign a private reference to a public instance method.

EXAMPLE

_classPrototype.myInstanceMethod = _classPrototype._myInstanceMethod = function () {
  // do stuff
};

In this example, the private instance method _myInstanceMethod is mapped to the public instance method myInstanceMethod. Inside the class' implementation, the private name can be used. This is useful if there will be many calls - in the class' implementation - to an instance method that's publicly accessible, as the private name will be reduced in size by the Scruncher.

IMPORTANT

Be careful when using this technique, because using a private reference to a public instance method doesn't ensure that a class' implementation will be calling a subclass' override of the instance method, since the subclass won't assign a value for the private identifier.
This technique is not useful for public instance properties that are expected to be assigned through the public interface, since assigning a value using the public name will not assign that same value to the private version.
This technique could be used for public instance properties that are intended to be read only and are not intended to be set outside of the class' implementation code. The technique could also be used if the value of the property was an object and was never intended to be changed, even if the contents of the object is expected to be modified by code outside of the class' implementation.

7. Non-inheritable Statics

Unless otherwise specified, all static features - methods as well as properties - of a Uize.Class subclass are inherited in turn by their subclasses.

There are times, however, when there is no compelling reason for a static feature of a class to be inherited by its subclasses. In fact, in some cases too many inherited static features can just clutter subclasses in the class hierarchy with cruft that they neither need nor care about. In such cases, the inheritance system of the UIZE JavaScript Framework provides a way to "register" static features of a class as being non-inheritable. This is done using the MyClass.nonInheritableStatics static property.

7.1. The MyClass.nonInheritableStatics Static Property

The MyClass.nonInheritableStatics static property is a lookup object, automatically created for a class, in which you can register the static features (methods or properties) of the class that should not be inherited when that class is subclassed.

Each property of the MyClass.nonInheritableStatics lookup object represents a single static feature of the class that should not be inherited by subclasses, where the name of each property should be the name of a static feature (excluding the module name), and the value of each property should be a truthy value (such as true, 1, 'foo', [], {}, etc.). After a class has been created, non-inheritable statics can be registered for that class by assigning properties to the class' MyClass.nonInheritableStatics static property, as shown in the example below...

EXAMPLE

MyClass = Uize.Class.subclass ();
MyClass.someUtilityFunction = function () {
  // do something of great utility
};
MyClass.nonInheritableStatics.someUtilityFunction = 1;

MyClassSubclass = MyClass.subclass ();
alert (MyClassSubclass.someUtilityFunction); // alerts the text "undefined"

In the above example, the MyClass.someUtilityFunction static method of the class MyClass has been registered as a non-inheritable static. This is done by the statement MyClass.nonInheritableStatics.someUtilityFunction = 1. Now, when the MyClassSubclass class is created by calling the MyClass.subclass method, the new subclass that is created does not get the someUtilityFunction static feature. Therefore, the alert statement displays the text "undefined" in the alert dialog.

7.1.1. nonInheritableStatics is a Non-inheritable Static

When a class is created, the MyClass.nonInheritableStatics static property is automatically initialized on that class to a fresh object with the value {nonInheritableStatics:1}.

This initial mapping means that the MyClass.nonInheritableStatics static property is, itself, not inheritable by subclasses - subclasses get their own fresh object. So, in our example, when the MyClassSubclass subclass is created, its fresh MyClassSubclass.nonInheritableStatics property does not have an entry for the someUtilityFunction static feature, because it does not have that static feature and the contents of the MyClass.someUtilityFunction object is not inherited by the MyClassSubclass class.

7.2. All Types of Statics Can Be Non-inheritable

All types of static features of a class can be registered as non-inheritable - methods as well as properties.

Registering static properties as non-inheritable is accomplished in the same way as for static methods. Consider the following example...

EXAMPLE

MyClass = Uize.Class.subclass ();
MyClass.someStaticProperty = 'foo';
MyClass.nonInheritableStatics.someStaticProperty = 1;

MyClassSubclass = MyClass.subclass ();
alert (MyClassSubclass.someStaticProperty); // alerts the text "undefined"

In the above example, the alert dialog would display the text "undefined", because the MyClass.someStaticProperty static property of the class MyClass has been registered as non-inheritable, so it is not inherited by the MyClassSubclass class that is created by subclassing MyClass.

7.3. Utility Functions Need Not Be Inheritable

A good case for making a static method non-inheritable is if it is really just a utility function that happens to be stashed in a class' namespace.

Static methods that are really just utility or helper functions don't care about the context on which they are called. They just happen to be called on a class as a context because they are assigned as properties on a class. Take, for example, the Uize.Fade.blendValues static method of the Uize.Fade class. You may be calling it on the Uize.Fade context, but this utility function's implementation doesn't even reference the this keyword - it just doesn't care about the context on which it is called. You could, in fact, assign this static method to a local variable and then call it using that local variable, and it would behave in just the same way as if it were being called on the class. Consider the following example...

EXAMPLE

var blendValues = Uize.Fade.blendValues;
alert (blendValues (50,100,.5));  // alerts the text "75"

In the above example, our local variable blendValues is a function reference. When that local variable is used to call the function in order to blend the values 50 and 100, everything works just fine. The alert statement alerts the result of blending 50 and 100 in equal amounts, which is the 75. Because the Uize.Fade.blendValues static method doesn't operate on a Uize.Fade subclass or need a Uize.Fade subclass as its context when it is called, there's no compelling reason for it to be inheritable, and so it is not.

7.4. When Statics Should Be Inheritable

Whenever a static method or property is intended to be unique to its class context, and it is also desirable for that method or property to be inherited by subclasses, then it should not be registered as non-inheritable.

Examples of some static methods in the Uize.Class base class that are inheritable are the Uize.Class.set, Uize.Class.get, Uize.Class.toggle, Uize.Class.fire, Uize.Class.wire, Uize.Class.subclass, and Uize.Class.registerProperties methods. All of these methods act on the class context. So, for example, calling Uize.Class.subclass is different to calling Uize.Widget.subclass. The Uize.Class.subclass method, which is inherited by all Uize.Class subclasses, uses the context of the class on which it is called. Calling the Uize.Class.subclass method returns a subclass of Uize.Class, while calling the Uize.Widget.subclass method returns a subclass of Uize.Widget - even though both of these methods reference the same function for their implementation (in other words, the statement alert (Uize.Class.subclass == Uize.Widget.subclass) would alert the text "true").

7.5. Inheritability of Static Features is Noted in Module References

All static features of modules of the UIZE JavaScript Framework are noted as being either inheritable or non-inheritable in the reference documentation for those features.

The inheritability of the static features of a module is noted in the IMPLEMENTATION INFO notes of the reference documentation for the features in the module's reference. So, for example, if you went to the reference documentation for the Uize.Class.set static method of the Uize.Class base class, you would see it noted that the feature is inherited by subclasses. In contrast, if you went to the reference documentation for the Uize.Fade.blendValues static method of the Uize.Fade class, you would see it noted that the feature is not inherited by subclasses.

8. Phases of Construction

When an instance of a UIZE class is created, construction involves three phases: the alphastructor phase, the set-get property initialization phase, and the omegastructor phase.

8.1. alphastructor

The alphastructor is a function that is executed before the set-get properties for an instance are initialized, and before the omegastructor function is executed.

An alphastructor is registered by specifying a value for the first parameter when calling the subclass static method on the superclass.

EXAMPLE

var MyClass = Uize.Class.subclass (
  function () {
    this._someArray = [];
  }
);

Code inside the alphastructor can set up private "scaffolding" type properties that need to be already in existence by the time any of the set-get properties are initialized. This allows onChange handlers for the set-get properties to count on certain foundation having been built.

Because of when it is executed, code inside the alphastructor function cannot rely on the instance's set-get properties being initialized to the values passed to the constructor.

EXAMPLE

var
  MyClass = Uize.Class.subclass (
    function () {
      alert (this.get ('foo'));
    }
  ),
  myClass = new MyClass ({foo:'bar'})
;

In this example, when the new instance of MyClass is created with the value 'bar' specified for its foo set-get property, the alert inside the alphastructor will display the value undefined. This is by design and is an important nuance to take note of.

8.2. omegastructor

The omegastructor is a function that is executed after the alphastructor function is executed, and after the set-get properties for an instance are initialized.

9. Dissecting a Subclass Module

9.1. An Example

Let's take a look at a skeleton of a subclass module, and then explore various aspects of it.

SUBCLASS MODULE EXAMPLE

Uize.module ({
  name:'Uize.Subclass',
  builder:function (_superclass) {
    /*** Class Constructor ***/
      var
        _class = _superclass.subclass (
          null, // typically don't need to do anything in the alphastructor
          function () {
            var _this = this;

            /*** Private Instance Properties ***/
              _this._privateInstanceProperty = 0;
          }
        ),
        _classPrototype = _class.prototype
      ;

    /*** Private Instance Methods ***/
      _classPrototype._privateInstanceMethod = function () {
        var _this = this;
        // implementation for this method
      };

    /*** Public Instance Methods ***/
      _classPrototype.publicInstanceMethod = function () {
        var _this = this;
        // implementation for this method
      };

    /*** Private Static-instance Methods ***/
      _class._privateStaticInstanceMethod =
      _classPrototype._privateStaticInstanceMethod = function () {
        // implementation for this method
      };

    /*** Public Static-instance Methods ***/
      _class.publicStaticInstanceMethod =
      _classPrototype.publicStaticInstanceMethod = function () {
        // implementation for this method
      };

    /*** Public Static Methods ***/
      _class.publicStaticMethod = function () {
        // implementation for this method
      };

    /*** Register Properties ***/
      _class.registerProperties ({
        _property1:'property1', // minimalistic approach to registering a property
        _property2:{
          name:'property2',
          onChange:function () {
            // do something when the value of this property changes
          },
          value:0
        }
      });

    return _class;
  }
});

NOTE: If you're not familiar with module declarations in the UIZE JavaScript Framework, consult the explainer JavaScript Modules.

9.2. The Superclass Reference

A reference to the superclass is provided as the parameter to the builder function. By convention, this is named _superclass.

This variable can then be used when creating the subclass, as in...

var _class = _superclass.subclass ();

The superclass reference can also be used when calling a superclass' version of an instance method, as in...

_classPrototype.wireUi = function () {
  var _this = this;
  if (!_this.isWired) {
    // do the wiring stuff

    _superclass.prototype.wireUi.call (_this); // call superclass version of wireUi
  }
};

9.3. Keeping a Class Reference

A reference to the newly created subclass is kept in a variable. By convention, this variable is named _class.

var _class = _superclass.subclass ();

This variable can then be used when assigning static methods and properties, as in...

_class.myStaticMethod = function () {
  // do stuff
};

...or when registering set-get properties, as in...

_class.registerProperties ({
  // profiles for the set-get properties
});

The reference to the newly created class is returned at the end of the builder function, as in...

return _class;

9.4. Keeping a Prototype Reference

A reference to the class' prototype property is stored in a _classPrototype variable.

var _classPrototype = _class.prototype;

This variable can then be used when assigning instance methods and properties that are to be shared by all instances, as in...

_classPrototype.myInstanceMethod = function () {
  // do stuff
};

9.5. Assigning an Instance Method

Using the _classPrototype reference, an instance method can be assigned for the class.

_classPrototype.myInstanceMethod = function () {
  // do stuff
};

IMPORTANT

It is easy to fall into the trap of ommitting the semi-colon when assigning an anonymous function to a property of the prototype object. Even though there is a function declaration, it is used as part of an assignment statement, and an assignment statement should end with a semi-colon. Leaving the semi-colon out will produce no symptoms until you scrunch the code and then another statement butts right up against your assignment, producing a syntax error. So, don't forget the semi-colon.

9.6. Assigning a Static Method

Using the _class reference, a static method can be assigned for the class.

_class.myStaticMethod = function () {
  // do stuff
};

In cases where you wish a static method to not be inheritable by subclasses of your class, you can register the method as non-inheritable as follows...

_class.myStaticMethod = function () {
  // do stuff
};
_class.nonInheritableStatics.myStaticMethod = 1;

For a more in-depth discussion, see the section Non-inheritable Statics.

9.7. Registering Set-get Properties

Set-get properties are registered for a class by calling the MyClass.registerProperties static method that is inherited from the Uize.Class base class.

The MyClass.registerProperties static method lets you register one or more set-get properties in a single call to the method. The single parameter that the MyClass.registerProperties static method takes is an object containing profiles for all the set-get properties being registered, where each key is the private name for a set-get property, and where each value is either the public name - or an object providing a complete profile - for the set-get property.

EXAMPLE

_class.registerProperties ({
  _property1:'property1', // minimalistic approach to registering a property
  _property2:{
    name:'property2',
    onChange:function () {
      // do something when the value of this property changes
    },
    value:0
  }
});

In the above example, the set-get property with the public name property1 is being mapped to the private identifier _property1. It is not technically necessary that the private name be the public name prefixed with an underscore - this is simply a convention that is followed. Because no object is used to specify the profile for this set-get property, there is no onChange handler registered, and the initial value is undefined. By contrast, the property2 set-get property is registered with a profile object that specifies an onChange handler function and an initial value of 0.