Object and Class System of Kekule.js

Kekule.js is an object-oriented chemoinformatics toolkit written in JavaScript. Developers usually need to dealing with objects and classes. Concepts in chemistry, such as atom, bond and molecule are represented as objects in the toolkit and different types of concepts deprived from different classes. The following simplified UML diagram shows some core classes and their relations of the toolkit.

../_images/coreClassesUml.png

< Simplified UML diagram of core classes >

Defining New Class

Developers can even deprive their own new classes from those existing ones. Traditionally, defining class in JavaScript involves in a lot of ugly and clumsy codes. In ES2015, the *class declaration* <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class> was introduced but unfortunately not supported by some ancient browsers (e.g., IE).

So in Kekule.js, a special approach is used. That approach provides a easy and neat way to define class and is runnable in ancient browsers (even IE8) as well.[#example]_

var MyCustomAtom = Class.create(Kekule.Atom, { // Creating a new class deprived from Kekule.Atom
  CLASS_NAME: 'MyCustomAtom',                  // Explicitly set the name of class
  initialize: function(id)             // Method initialize will be regarded as constructor of class
  {
    this.applySuper('initialize', [id]);     // Use applySuper function to call inherited method from ancestor class
    this._customText = 'My value';
  },
  initProperties: function()                   // Special method, defining new properties of class
  {
    this.defineProp('myProperty', {            // defining integer property: myProperty
      'dataType': DataType.INT,
      'getter': function() {
        console.log('Reading myProperty');     // additional operation in property getter
        return this.getPropStoreFieldValue('myProperty');  // return value from default storing field of object
      },
      'setter': function(value)
      {
        console.log('Writing myProperty');     // additional operation in property setter
        this.setPropStoreFieldValue('myProperty', value);  // set value to default storing field of object
      }
    });
    this.defineProp('customText', {            // defining string property: customField
      'dataType': DataType.STRING,
      'getter': function() { return this._customText; },      // return value from a custom storing field
      'setter': function(value) { this._customText = value; } // set value to a custom storing field
    });
  },
  showNewPropertyValues: function()            // defining new method
  {
    console.log(this.getMyProperty(), this.getCustomText());
  }
});

Note

In the past versions of Kekule.js, special $super argument is utilized to call inherited method, something like:

initialize: function($super, id)
{
  $super(id);   // Use $super parameter to call inherited method from ancestor class
  this._customText = 'My value';
}

However, that approach often causes problem in modern package tool like WebPack. So in recent versions, applySuper is recommended instead.

Method Class.create is used to create a new class and this method accept two parameters. The first parameter is the ancestor class which can be omitted if the new class does not inherit from any existing ones. The second parameter is a JavaScript object defining the methods and attributes of new class. Among those methods, there are two special ones: initialize plays as the constructor of class and initProperties defines all new properties of this class.

In Kekule.js class system, property is a little different from traditional JavaScript property. In order to avoid compatiblity problems in different web browsers, property need be accessed by getter and setter methods (e.g getMyProperty(), setCustomText('Text')). Aside from read/write value to property itself, getter and setter methods are able to perform some additional operations as shown in the previous example.

Create Instance of Class

After defining the new class, developer can create new instances same as traditional JavaScript:1

var myInstance = new MyCustomAtom('myId');  // create new instance
myInstance.setMyProperty(10).setCustomText('Custom Text');  // set property values
myInstance.setSymbol('Cl');   // set property value inherited from ancestor classes
console.log(myInstance.getAtomicNumber());  // get property value inherited from ancestor classes
var dupInstance = myInstance.clone();        // access inherited method
console.log(
  dupInstance.getSymbol(),
  dupInstance.getMyProperty(),
  dupInstance.getCustomText()
);

Serialize/deserialize of Object

Kekule.js provides methods to save/load class instances to/from JSON or XML. Different from traditional JSON approaches, those methods usually only save/load defined properties of object. 1

var jsonData = {};
myInstance.saveObj(jsonData, 'json');
var newInstance = new MyCustomAtom();
newInstance.loadObj(jsonData, 'json');
console.log(
  newInstance.getSymbol(),
  newInstance.getMyProperty(),
  newInstance.getCustomText()
);
1(1,2)

Example of this chapter can be found and run at here.