Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top