Question

I have a "SuperClass" with "info" as an instance variable. "SuperClass" has function "printInfo()". "printInfo()" needs to access instance variable "info". I want to create a "SubClass" which also has method "printInfo()". I want to call printInfo() of "SuperClass" from "printInfo()" of "SubClass".

SuperClass = function()
{
    this.info = "I am superclass";
    console.log("SuperClass:");
};

SuperClass.prototype.printInfo = function(that)
{
    console.log("printing from superclass printInfo");
    console.log(that.info);
};

SubClass = function(){};

SubClass.prototype = new SuperClass();

SubClass.prototype.printInfo = function()
{
    console.log("calling superclass");
    this.constructor.prototype.printInfo(this);
    console.log("called superclass");
};

var sc = new SubClass();
sc.printInfo();

You can see that I am passing "that" as a parameter to printInfo. Without "that" parameter, "info" is printed as "undefined". Like in the following case, "this.info" is undefined when this function is called from object of "SubClass".

SuperClass.prototype.printInfo = function()
    {
        console.log("printing from superclass printInfo");
        console.log(this.info);
    };

What is the proper way to override and invoke methods of superclass in javascript, enabling functions to access instance variables of the class?

Was it helpful?

Solution

You are messing with the SubClass's prototype with the SuperClass's object, in this line

SubClass.prototype = new SuperClass();

the child's prototype should depend on the Parent's prototype. So, you can inherit like this

SubClass.prototype = Object.create(SuperClass.prototype);

Also, it is quite normal to change the constructor to the actual function, like this

SubClass.prototype.constructor = SubClass;

To keep your implementation generic, you can use Object.getPrototypeOf, to get the parent prototype in the inheritance chain and then invoke printInfo, like this

SubClass.prototype.printInfo = function() {
    Object.getPrototypeOf(SubClass.prototype).printInfo(this);
};

Since, info is defined in the SubClass yet, it will print undefined. You might also want to call the parent't constructor, like this

var SubClass = function() {
    SuperClass.call(this);
};

Note: You are creating global variables, by omitting var keyword before SuperClass and SubClass.

OTHER TIPS

After reading all the answers, I am using the following inheritance mechanism:

var SuperClass = function()
{
    this.info = "I am superclass";
    console.log("SuperClass:");
};

SuperClass.prototype.printInfo = function()
{
    console.log("printing from superclass printInfo");
    console.log("printinfo");
    console.log(this.info);
};

var SubClass = function(){
    SuperClass.call(this);
};

SubClass.prototype = Object.create(SuperClass.prototype);
SubClass.prototype.constructor = SubClass;

SubClass.prototype.printInfo = function()
{
    console.log("calling superclass");
    Object.getPrototypeOf(SubClass.prototype).printInfo.call(this);
    console.log("called superclass");
};

var sc = new SubClass();
sc.printInfo();
class Thing {
  constructor(age) { this.age = age; }
  die(how) { console.log(`Died of ${how}`); }
}

class Me extends Thing {
  constructor() { super(59); console.log(`I am ${this.age}`); }
  // Refer to a method from the superclass that is overridden in the subclass
  die(how) { super.die('liver failure'); console.log(`while ${how}`) }
}

(new Me()).die('hang gliding');

You can write it like this :

SuperClass.prototype.printInfo = function(){
  console.log("printing from superclass printInfo");
  console.log(this.info); 
};

SubClass.prototype.printInfo = function(){
  console.log("calling superclass");
  SuperClass.prototype.printInfo.call(this);
  console.log("called superclass");
};

For anybody who comes more from a Java world I would ignore all of the above and use the following syntax instead that was introduced in 2015

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
} 

More info on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

And suddently u can use super as keyword to access ancester etc.... For me finding this was a big relief

@coolscitist

Instead of

SubClass.prototype.printInfo = function()
{
    Object.getPrototypeOf(SubClass.prototype).printInfo.call(this);
};

use this

SubClass.prototype.printInfo = function()
{
    Object.getPrototypeOf(this.constructor.prototype).printInfo.call(this);
};

The only way I've been able to sort this out is to save the parent's function in different variable before overriding in the child class definition.

var Foo = function(){
    var self = this.
    this.init = function(a,b){
        self.a = a;
        seld.b = b;
    };
}

var Goo = function(){
    Foo.apply(this);
    var self = this;
    self.Foo = { init: self.init };//saves the super class's definition of init in a new variable
    self.init = function(a,b,c){
       self.Foo.init(a,b);//can call the super class function
       self.c = c;
    };
}

var a = new Foo();
a.init(1,2);
var b = new Goo();
b.init(1,2,3);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top