Skizit
Skizit

Reputation: 44872

Node Inheritance with require / prototype

I've got an abstract object defined like so...

var abs = module.exports = function abs(val){

   if(!(this instanceof abs)){

      return new abs(val);

   }

   abs.prototype.getName = function getName(){

      return val.name;

   }

}

and a concrete class that I want to inherit from it defined like so...

 var concrete = module.exports = function concrete(val){

    var abs = require('./abs');

    if(!(this instanceof concrete)){

       return new concrete(val);

    }

    concrete.prototype = Object.create(abs.prototype);

 }

and when I write...

 var anObject { name : "John" };
 var concreteObject = new concrete(anObject);
 concrete.getName();

I get the following error..

TypeError: Object #<conrete> has no method 'getName'

What am I doing wrong?

Upvotes: 0

Views: 102

Answers (1)

Bergi
Bergi

Reputation: 665574

There are two errors (left alone the missing =) in what your wrote:

  • concrete.getName() does not work because concrete is your constructor function. It has no such method.
  • concreteObject.getName() does not work because its prototype has no such method. You did overwrite concrete.prototype in the constructor, but then the instance was already built with the old one. Check how the new operator works.

Therefore you need to fix those class definitions as well. As we've seen, one cannot access constructor arguments from the shared prototype functions - it would not make any sense. And assigning the prototype methods in the constructor would make the val of the latest abs invocation available to all instances. Ugh.

Use the prototype:

function abs(val) {
    if (!(this instanceof abs))
        return new abs(val);

    this.val = val;
}
abs.prototype.getName = function getName(){
    return this.val.name;
};
module.exports = abs;

or use a privileged instance method (see Javascript: Do I need to put this.var for every variable in an object? for explanations):

function abs(val){
    if (!(this instanceof abs))
        return new abs(val);

    this.getName = function getName(){
       return val.name;
    };
}
module.exports = abs;

As for that concrete thing, I don't understand why you need it at all - it doesn't seem to do much more than concrete = abs; would do. However, the blueprint for inheritance would look like this:

var abs = require('./abs');
function concrete(val){
    if (!(this instanceof concrete))
        return new concrete(val);

    abs.call(this, val);
}
concrete.prototype = Object.create(abs.prototype);

Upvotes: 1

Related Questions