Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js: how to 'inherit' from abstract class?

Tags:

oop

node.js

I'm building a web app with node.js (+ angular, etc.).
The app will have to retrive some data (something like a catalog items list) from different providers, who expose their data in different ways.

In that module, I will have some function common to all providers, and some function unique to any of them.

My current (poor) implementation is something like this:

var providers = [
  {  name: 'Apple', /* ... */ },
  {  name: 'Samsung', /* ... */ },
  {  name: 'Google', /* ... */ },
];

exports.syncCatalogues = function(search, callback) {
  var allItems = [];
  for (var p = 0; p < providers.length; p++) {
    exports.getCatalog(providers[p], function(err, catalog) {
      if (err) {
        return callback(err);
      }
      exports.getItems(providers[p], catalog, function(err, items) {
        if (err) {
          return callback(err);
        }
        allItems = allItems.concat(items);
        callback(null);
      });
    });
  }
};

And my getCatalog() and getItems() implementation are as ugly as this:

exports.getCatalog(provider, callback) {
  if (provider.name === 'Apple') {
    // code for Apple provider ...
  }
  // and so on ...
};


exports.getItems(provider, callback) {
  if (provider.name === 'Apple') {
    // code for Apple catalog ...
  }
  // and so on ...
};

I know with ES5 (I'm stuck to it) abstract classes are not easy to implement, but I'm sure there is a better way (code more readable, maintainable, testable) than this... :-(

like image 701
MarcoS Avatar asked Feb 10 '16 15:02

MarcoS


3 Answers

There are many ways to implement the inheritance in JavaScript. Here is one, which I think the simplest, since you just operate with plain objects and use prototypal inheritance.

Instead of the base class you have a prototype object where you can place the common code. Then you create an object based on the prototype and add specific code to it.

var providerPrototype = {
  name: 'Prototype',
  alertName: function() {  // this is common function, all objects
    alert(this.name);      // will have it
  }
};

var appleProvider = Object.create(providerPrototype);
appleProvider.name = 'Apple';
// this is a specific function for 'Apple'
appleProvider.getCatalog = function(callback) {
  return callback(null, ['iPhone', 'Mac Mini']);
}
appleProvider.alertName = function() {
   // call 'base' method
   providerPrototype.alertName.call(this);
   alert('All rights reserved.');
}

var samsungProvider = Object.create(providerPrototype);
samsungProvider.name = 'Samsung';
// this is a specific function for 'Samsung'
samsungProvider.getCatalog = function(callback) {
  return callback(null, ['Galaxy S3', 'Galaxy S4']);
}

var providers = [
  appleProvider, samsungProvider
];

var syncCatalogues = function(search, callback) {
  var allItems = [];
  for (var p = 0; p < providers.length; p++) {
    var aProvider = providers[p];
    aProvider.getCatalog(function(err, catalog) {
      if (err) {
        return callback(err);
      }
      aProvider.alertName(); // call the base method
      alert(catalog);
    });
  }
};

syncCatalogues();

Check also Inheritance and the prototype chain in Mozilla javascript documentation.

And here is an example of splitting classes over node.js modules.

like image 153
Boris Serebrov Avatar answered Oct 13 '22 01:10

Boris Serebrov


I'm new in nodeJS but I think my code below is possible only after ES6. I hope to help newbies like me. Follows:

class BaseClass {
    constructor(){
        console.log('Object created INHERITED');
    }

    toCallFromChild(){
        console.log('Called by child');
        this.toOverride();
    }

    toOverride(){} //to override
}

class childClass extends BaseClass{
    toOverride(){
        console.log ('Override by child');
    }
}

var instance = new childClass();
instance.toCallFromChild();
like image 4
Guilherme Muniz Avatar answered Oct 13 '22 01:10

Guilherme Muniz


My response is a possible alternative solution.

I personnally do not like the native javascript object mecanics. So i generaly use a library like Mootools for making clean objects.

Example from Mootools documentation :

var Animal = new Class({
    initialize: function(age){
        this.age = age;
    }
});
var Cat = new Class({
    Extends: Animal,
    initialize: function(name, age){
        this.parent(age); // calls initalize method of Animal class
        this.name = name;
    }
});
var myCat = new Cat('Micia', 20);
alert(myCat.name); // alerts 'Micia'.
alert(myCat.age); // alerts 20.

Se the online doc on : http://mootools.net/

like image 2
Ifnot Avatar answered Oct 13 '22 00:10

Ifnot