1

This has probably been asked in some form and I tried to check this resource: https://developer.mozilla.org/en/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

My gameobject.js looks like this:

function GameObject(program)
{
    this.program = program;
    this.graphics = null;
}

GameObject.prototype.update = function(dt)
{

}

GameObject.prototype.draw = function()
{
    // Here graphics would be the graphics of the child class, 
    // because the graphics would be replaced with the child class' graphics
    if(this.graphics !== null)
        this.program.renderer.render(this.graphics);
}

And I want to have another class called, for example, box.js:

function Box(program, width, height, x, y)
{
    // Call base constructor here?

    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
}

And Now I want to basically inherit the update and draw methods from GameObject as well as call the GameObject constructor with the program parameter, so that in the end the thing should work like this:

var box = new Box(program, 10, 10, 100, 100);

// In game class update method
box.update(this.td);

// In game class draw method
box.draw();

So basically like how it would be done in C#. It would already help a lot, if only I could get the Box to inherit the update and draw methods from the GameObject.

Edit 1: Jsfiddle here: https://jsfiddle.net/0df9rfu5/1/

Edit 2: I tried a workaround like this:

function Box(program, width, height, x, y)
{
    var self = this;

    this.base = new GameObject(program);

    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;

    this.update = function(dt) { self.base.update(dt); };
    this.draw = this.base.draw();
}

So I would be creating a new instance of the base class GameObject every time a Box is created and then I set the box' update and draw methods to those of GameObject.

This isn't doing the trick though and I think there is something deeply wrong with this method any way.

Edit 3: Maybe I should just do this like I've always done... everything that inherits from GameObject still has to override the update and draw methods. It is just that I guess I can't be sure that every object in gameobject list has draw and update methods and I will just have to assume they do.

Swiffy
  • 4,401
  • 2
  • 23
  • 49
  • So you want `GameObject` to inherit from `Box`? Have a look [here](https://stackoverflow.com/questions/10898786/correct-javascript-inheritance/) – Bergi Apr 06 '16 at 11:08
  • @Bergi No the other way around. Box should inherit from GameObject and then Box should override GameObject's draw and update methods. This way I can make a list of GameObjects and put Boxes and stuff in it and be sure that each object in the list has draw and update methods. – Swiffy Apr 06 '16 at 11:10
  • @Bergi I guess I really should not be thinking JavaScript as class-based OOP at all, as it does not seem to work without workarounds and shims. – Swiffy Apr 06 '16 at 11:12
  • OK, then the other way round, shouldn't make a difference. But notice that you don't *need* inheritance in JS only to create a heterogeneous list. – Bergi Apr 06 '16 at 11:12
  • Yes, you can certainly use a class-based approach (classes are a very useful concept after all!), but you need to remember that you're implementing the concept with prototypal OOP. – Bergi Apr 06 '16 at 11:13

1 Answers1

1

Constructors in JavaScript are just plain functions. To call GameObject from inside the Box constructor you would use:

GameObject.call(this, program);

To have Box objects inherit form GameObject use

Object.setPrototypeOf(Box.prototype, GameObject.prototype);

Be sure to put the line above before the first invocation of new Box.

For best compatibility with older browsers (tanks @Bergi), you can overwrite Box.prototype with a new object instead of using Object.setPrototypeOf.

Box.prototype = Object.create(GameObject.prototype, { configurable: true, writable: true, value: Box });

Then you should be able to use the methods draw and update on Box objects.

The example below should get you on the right track

function GameObject(program)
{
    this.program = program;
    this.graphics = null;
}

GameObject.prototype.update = function(dt)
{
    alert('updating');
}

GameObject.prototype.draw = function()
{
    // Here graphics would be the graphics of the child class, 
    // because the graphics would be replaced with the child class' graphics
    if(this.graphics !== null)
        this.program.renderer.render(this.graphics);
}

function Box(program, width, height, x, y)
{
    GameObject.call(this, program);

    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
}

Object.setPrototypeOf(Box.prototype, GameObject.prototype);

let b = new Box();

b.update();
GOTO 0
  • 42,323
  • 22
  • 125
  • 158
  • Notice that `Object.create` is much better supported than `Object.setPrototypeOf` – Bergi Apr 06 '16 at 11:20
  • If I do `this.graphics = new Graphics()` inside the Box constructor, will the draw function see it as not null anymore? – Swiffy Apr 06 '16 at 11:20
  • @Bergi In fact `Object.setPrototypeOf` is not supported in older Safari browsers. Anyway, if `Box.prototype` is overwritten, then `Box.prototype.constructor` needs to be manually assigned as an own property. – GOTO 0 Apr 06 '16 at 11:27
  • @Piwwoli Sure, if you do it after calling `GameObject`. – GOTO 0 Apr 06 '16 at 11:28
  • @GOTO0: It's not supported in *any* older browser, and needs to be shimmed using `__proto__` if that is available. `Object.create` only requires ES5, that's what I meant. If you use ES6, you might as well use `class` right away :-) – Bergi Apr 06 '16 at 11:29
  • @GOTO0 Then this is probably the best answer to this question. Thanks. I will mark this as accepted. – Swiffy Apr 06 '16 at 11:34
  • @Piwwoli you're welcome. If you need compatibility with older browsers you can adopt Bergi's suggestion. I've updated my answer to include this. – GOTO 0 Apr 06 '16 at 11:52
  • Hmm this seems to somehow stack all my Boxes into same positions / think of all boxes as one. Could be a problem with my code though. – Swiffy Apr 06 '16 at 12:09
  • @Piwwoli That's weird. Maybe make sure you're now reusing the same object in some way. – GOTO 0 Apr 06 '16 at 12:13