Taylor Lopez
Taylor Lopez

Reputation: 863

Returning the proper child type when calling inherited parent method in JavaScript

Let's say I have this parent class Vector2 defined as follows:

function Vector2 (x, y) {
  this.x = x;
  this.y = y;
}
Vector2.prototype.add = function(vec) {
  console.log(Reflect.getPrototypeOf(this));
  if (vec instanceof Vector2)
    return new Vector2(this.x + vec.x, this.y + vec.y);
  throw "This operation can only be performed on another Vector2. Recieved " + typeof vec;
};

And an extension of Vector2 called Size that should inherit all the functional goodness of its parent, with the aditional ability to reference x and y as w and h respectively, like so:

function Size(x,y) {
  this.x = x;
  this.y = y;
}
Size.prototype = new Vector2;
Size.prototype.constructor = Size;
Size.prototype._super = Vector2.prototype;
Object.defineProperties(Size.prototype, {
  'w': {
    get: function() {
      return this.x;
    },
    set: function(w) {
      this.x = w;
    }
  },
  'h': {
    get: function() {
      return this.y;
    },
    set: function(h) {
      this.y = h;
    }
  }
});

Finally, I have a code snippet that creates two new instances of Size, adds them together, and attempts to read from the w property like so:

var s1 = new Size(2, 4);
var s2 = new Size(3, 7);
var s3 = s1.add(s2);
console.log(s3.w);
// 'undefined' because s3 is an instance Vector2, not Size

How can I modify Vector2's add method to create a new instance of whatever the current class is rather than a generic one?

Upvotes: 1

Views: 38

Answers (2)

trincot
trincot

Reputation: 350137

You have an error in your getter code: instead of self you need to use this.

Then you can call the correct constructor with:

return new this.constructor(this.x + vec.x, this.y + vec.y);

NB: You could also use vec.constructor, it all depends what you want to happen when you add a Size object to a Vector object. It seems more intuitive to me that the source object (on which the add method is applied) determines the class of the returned object. If you feel the added object should determine the returned object's class, then use vec instead of this.

Upvotes: 2

Kyle Richardson
Kyle Richardson

Reputation: 5645

I believe this might be what you're looking for.

return new vec.constructor(this.x + vec.x, this.y + vec.y);

Use the constructor of what is passed to add method to create your returned object.

You're also passing this to your new Vector2( this, ... ) erroneously.

Upvotes: 2

Related Questions