0

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?

4
  • I don't think you should be assigning stuff to the prototype inside a constructor. Commented Sep 19, 2013 at 23:26
  • @Musa if I don't then val becomes undefined in the prototype functions. Commented Sep 19, 2013 at 23:32
  • @Skizit: That's the point of prototypes - they are shared amongst all instances and cannot access their scopes. Commented Sep 19, 2013 at 23:47
  • @Bergi I see. What would be the correct way to do what I'm trying to achieve? Commented Sep 19, 2013 at 23:52

1 Answer 1

1

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);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.