Ahmed Drar
Tera Guru
Tera Guru

A few days ago I saw a question on the ServiceNow community about how inheritance works in a script include so I thought to write a short article about that.

In Script include we can write a function or we can create a class. In JavaScript, class is an object, an object can access properties and functions from another object, this we call Inheritance

Inheritance is a great way to create a parent/child hierarchy of classes. A good use case for inheritance is when you wish to indicate that one object is mostly similar to another, but with some variations.

Parent class(Base class) is a class that supplies base behavior to a child class. The child class then extends this base behavior to form its behavior

Let's take an example

Suppose you would like to create a script that handles the behavior of tasks and incidents. as you know, a lot of behavior is in common between task and incident, so When crafting a task script, you should be crafting it in a way that can be open to an extension so that incident's script can come along and build upon the task behavior.

Let's write some code to see how this works in reality.

I create a class named TaskParentClass. The class takes GlideRecord as a parameter and contains three methods. those methods can work on Task and Incident.

var TaskParentClass = Class.create();
TaskParentClass.prototype = {
    initialize: function() {
	
    },
	WelcomeToTask:function(gr){
		
		gs.addInfoMessage('Welcome to task Number ' + gr.number);
	},
	getCI:function(gr){
		
		gs.addInfoMessage('CI Name is ' + gr.cmdb_ci);
	},
    type: 'TaskParentClass'
};

 

Now, Let's create a child class that inherits TaskParentClass. We are going to inherit the class using Object.extendsObject method.

var IncidentChildClass = Class.create();
IncidentChildClass.prototype = Object.extendsObject(TaskParentClass, {
    initialize: function() {
	
    },
getCaller:function(gr){
	
	gs.addInfoMessage('Caller Name is' + gr.caller_id.name);
},
    type: 'IncidentChildClass'
});

after extending the class using Object.extendsObject method, we expect all parent methods to be available to the child as well as 'getCaller' method which is implemented in the child class.

 let's validate that we can access parent & child methods by calling two methods, one from the parent and one from the child

// Calling Method from Parent Class
	new IncidentChildClass().WelcomeToTask(current);
// Calling Method from the current class
	new IncidentChildClass().getCaller(current);

 

find_real_file.png

Comments
dougconnell
Kilo Guru

The problem with this example of inheritance, is that it is not obvious how to call the initialize() function (constructor) of the parent class if you include an initialize() function in the child class.  

 

see: Inheritance revisited - ServiceNow Community for a way to do this.

 

For ES5, there is a another pattern for inheritance:

See:  Classical Inheritance in JavaScript ES5 - DZone Web Dev

 

I have successfully used this pattern for Script Includes. 

Although to be honest, I prefer composition to inheritance.  Composition is usually preferable to inheritance because it hides the implementation of your parent class - which gives you more freedom to change the parent class without any negative consequence.    a minimal (MVP) interface is best.
"Hiding the Implementation" (with a minimal but optimal interface) is a key concept.  Blackbox protection of core functionality - which can be then be easily  "upgraded" without any issues around backwards compatibility is critical -   A lesson many vendors struggling with - IMHO.

Ahmed Drar
Tera Guru
Tera Guru

Thanks @dougconnell ! spot on. I love composition as well, however i think there is time & place for each one of them. 

 

in my mind, we use composition when class to class relationship is 'has' rather than 'is'.

 

so when we say John is human, John can inherit human class but when say John has arm, then this is a composition  

Version history
Last update:
‎03-06-2022 03:49 AM
Updated by: