Thursday, February 23, 2012

JavaScript OOP - type checking and inheritance

When working on large project, likely requiring a large OOP structure for coherence, it is important to have consistent types. If you're expecting an object to have this property or that method, it should be there. In fact a major benefit of working with a statically typed language such as Java or Objective-C, is that variable type is determined at compile time, is that variable type is strictly enforced. For example, when a function receives a parameter that is of incorrect type, a compile time warning or error can be generated. By contrast, JavaScript is dynamically typed (determined at runtime). This can lead to type runtime errors that can be difficult to track down.

To combat this, the instanceof operator can be used to enforce type. instanceof B evaluates to true when a is an instance of B, simple enough. What is really interesting is that when using the inheritance method outlined previously instanceof can also be used to determine if an object inherits from a prototype as well as implementing one.

//Create prototypes
var classA = function(){};
var classB = function(){};
classB.prototype = new classA(); //classB inherits from classA

var a = new classA();
var b = new classB();

//a is not identified as an instance of classB,   
console.log(a instanceof classA); //true
console.log(a instanceof classB); //false

//b is identified as an instance of classA. 
console.log(b instanceof classB); //true
console.log(b instanceof classA); //true


Here is a quick example of how to use this in a function to enforce type safety.

//function that requires classB
function needsClassB(b){
  if(!(b instanceof classB)){
    throw("needsClassB passed invalid argument: "+b);
  }

  console.log("we can do super awesome classB only stuff!");
}

//objects
var a = new classA();
var b = new classB();

needsClassB(b); //we can do super awesome classB only stuff!
needsClassB(a); //throws error

This lacks the elegance of defining types in the method definition, as you would in Java or Objective-C, but JavaScript often requires compromise. And this technique provides as least a measure of certainty that the arguments are going to be what is expected.

No comments:

Post a Comment