Helma Logo
main list history
previous version  overview  next version

Version 1 by luchkovsky on 21. April 2007, 12:24

Lazy Inheritance is an approach intended to simplify writing OOP and provides support of prototype-based classes hierarhies, automatic resolving and optimizing classes dependencies.

= Overview =
"Lazy inheritance" is a design pattern used in JavaScript computer programming. It designates a postponed linking of an object with it's prototype (class) until it is needed. If used properly, such approach may increase efficiency, simplicity and flexibility of OOP based code written using JavaScript. Unlike of classical prototype-based approach, it supports a "Lazy" way of inheritance implementation, since reference to parent class is invoked only at the moment of object instance creation.
Basically, it's possible to say that instances of objects in such approach are created in "mixed" mode – on first invocation, an appropriate factory is used to modify object constructor prototype which is later used for subsequent object instances creation.
Moreover, since "Lazy inheritance" is called only once at the moment of first object instance creation, it becomes possible to combine process of class prototype creation with resolving necessary dependencies of that class. In other words, the process of prototype construction also allows loading scripts (if ones were not loaded before) which particular class depends on.

== Benefits ==
Such approach to inheritance support has the following benefits:
* Lazy inheritance has the same benefits as classical JavaScript prototype features;
* It is not necessary to maintain proper order of script files declaration;
* In most cases, HTML page is loaded faster since there are no objects created during page initialization and since some scripts could be loaded only at the moment in which they are actually necessary (they are necessary if the caller code during it's execution really creates instances of corresponding classes);
* Dependencies are declared in more explicit way and class depends only on concrete scripts; Moreover, it's not necessary to artificially group particular scripts into "modules" and define dependencies between such "modules";
* If lazy mode of scripts loading is used, only necessary scripts (which are actually required for application functionality) will be loaded. If, for example, some HTML page may operate in different modes, like "read-write" and "read-only", for every mode required scripts will be loaded and this will be performed automatically without manual script loading optimization.

== Lazy Inheritance Internals ==
"Lazy inheritance" is invoked within the Object' constructor code and is called only once for first object instance creation.
After invocation, the following steps:
* First, the algorithm tests Object' dependencies;
* If Object' dependency had been registered before the object constructor was called (interrelations can be defined in the object constructor too), corresponding JavaScript dependencies are loaded.
* Then, if the class, from which the object inherits, is defined and it is not a default one (Object), Object's constructor prototype is modified by classical schema of prototype-based inheritance.
* After completing prototype modification, constructor of the Object' is called again to apply changes to new instance of the Object.

The derived instance of the Object may be modified in the constructor according to particular logic. For example, some properties of the object may be defined.
The resulting object is the same JavaScript object as it would be created with prototype-based inheritance.

== Example ==

First, we define Person.
Let's assume that declaration of that class is placed to person.js JavaScript file.

  /**
    * Constructor for Person class
    */
  function Person(aName)
  {
    this.fName = aName;
  }
  /**
    * Function which returns name of Person’s.
    */
  Person.prototype.getName = function()
  {
    return this.fName;
  };
  /**
    * Here we define function which returns
    * string representation of Person
    * assign it to prototype of Person class
    */
  Person.prototype.toString = function()
  {
    return "Person: " + this.getName();
  };

Here we assume that the code below is placed to employee.js file.

  /*
  * Here we define that Employee class
  * depends on person script.
  */
  JSINER.addDependency( {Employee:"person"} );
  /**
  * Here we define constructor for Employee class
  * and declare that Employee class inherits Person one
  */
  function Employee(aName, aUID)
  {
    var self = JSINER.extend(this, "Person");
    self.fName = aName;
    self.fUID = aUID;
    return self;
  }
  /**
  * Here we define function which return UID of employee
  * and assign it to prototype of Employee class.
  */   
  Employee.prototype.getUID = function()
  {
    return this.fUID;
  };
  /**
  * Here we define function which returns
  * string representation of Employee
  */
  Employee.prototype.toString = function()
  {
    var person = Employee.superClass.toString.call(this);
    return this.getUID() + ":" + person;
  };

And this is sample HTML page which uses declarations of JavaScript object above:

  <html>
    <head>
      <title>Lazy inheritance example.</title>
      // We need to include reference to JSNIER code
      <script src="script/jsiner.js"></script>
      // Note that we include reference to
      // script that contains Employee class only
      <script src="script/employee.js"></script>
      // And no it's not required to
      // reference person.js script explicitely -
      // JSINER will resolve and load it automatically
      <!--<script src="script/person.js"></script>-->
  </head>
  <body>
    <script>
        var employee = new Employee('John Doe', 1212);
        alert(employee);
      </script>
  </body>
</html>

During execution of example code listed above, linkage of Employee and Person as well as
loading of necessary script "person.js" is performed automatically with the first creation of Employee instance.

As it is illustrated by examples above, "Lazy inheritance":
* It is called only once during first creation of object instance;
* Linkage of objects and scripts is performed automatically;
* To link classes the prototype based inheritance is used.

In general, the proposed scheme considers "lazy" loading as primary mode for loading particular scripts. However, this is not strict requirement – it is also possible to force loading of all scripts which form particular application before starting objects creation if this way of loading is required by particular application architecture.

= Where it works =
Proposed Lazy inheritance approach was tested under
* Windows Internet Explorer 6.0/7.0
* Mozilla Firefox 1.5/2.0
* Opera 9.10
* MAC Safari 2.03
* MAC Firefox 1.5.0.11
* MAC Opera 9.0

= Lazy Inheritance Implementation =
* http://www.ajaxline.com/node/367 Lazy Inheritance on AjaxLine
* http://www.soft-amis.org/jsiner  JSINER page on SoftAMIS
* http://sourceforge.net/projects/jsiner JSINER page on SourceForge


     removed
     added