继承:如何在重写方法中模拟super.method

时间:2013-01-14 12:49:37

标签: javascript inheritance override

我正在尝试以最简单的方式实现继承。我知道JS继承是基于原型的,但由于我对基于OO类的语言更熟练,我在某种程度上偏向于将“类”逻辑封装在“构造函数”函数中。此外,我试图避免在原型对象中定义新成员,因为该代码应该放在“类”函数之外。这是我试过的:

    function Car(color, year, plate) { 
        this.color = color;
        this.year = year;
        this.plate = plate;
        this.hasFuel = true;
        this.fuel = 100;    

        this.run = function(km) {
            this.fuel = this.fuel - km*this.getFuelConsumptionRate(); 
            if(this.fuel < 0){
                this.fuel = 0;
            }
            if(this.fuel == 0){
                this.hasFuel = false;
            }
        };  

        this.getFuelConsumptionRate = function(){
            return 4.2;
        };
    }

    function EfficientCar(color, year, plate, weight){
        //Emulating a super call
        Car.call(this, color, year, plate);

        this.weight = weight;

        //Overriden method
        this.getFuelConsumptionRate = function(){
            return 2.2;
        };  
    }
    //Inheritance 
    //(I don't like this out of the method, but it is needed for the thing to work)
    EfficientCar.prototype = Car;
    EfficientCar.prototype.constructor = EfficientCar;

此代码按预期工作:高效汽车在呼叫运行相同的公里数后剩余燃料更多。但是现在我想在覆盖子版本中使用函数的父版本。像这样:

    function EfficientCar(color, year, plate, weight){
        //Emulating a super call
        Car.call(this, color, year, plate);

        this.weight = weight;

        this.getFuelConsumptionRate = function(){
            return super.getFuelConsumptionRate() / 2;  //If only I could do this...
        };  
    }

有没有办法以类似的方式实现这一目标?我希望几乎所有内容都在CarEfficientCar 中,对不起,函数。

3 个答案:

答案 0 :(得分:2)

如果你想在javascript中使用继承,我建议你使用John Resig的这个小宝石:

http://ejohn.org/blog/simple-javascript-inheritance/

博客示例:

var Person = Class.extend({
  init: function(isDancing){
    this.dancing = isDancing;
  },
  dance: function(){
    return this.dancing;
  }
});

var Ninja = Person.extend({
  init: function(){
    this._super( false );
  },
  dance: function(){
    // Call the inherited version of dance()
    return this._super();
  },
  swingSword: function(){
    return true;
  }
});

var p = new Person(true);
p.dance(); // => true

var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true

// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class

答案 1 :(得分:1)

如果你想调用“superclasse”中定义的函数,你应该正确使用原型,即在原型上定义函数,而不是在实例上:

Car.prototype.getFuelConsumptionRate = function() {
 return 4.2; 
}

的继承
EfficientCar.prototype = new Car();

然后,你可以调用超级函数:

EfficientCar.prototype.getFuelConsumptionRate = function(){
   var superfun = this.constructor.prototype.constructor.prototype.getFuelConsumptionRate;
   return superfun.call(this) / 2;
};  

Complete demonstration(打开控制台)

你调用超级函数(在我看来是一个糟糕的函数)是一种练习,然后你可以构建一个嵌入和缩短方法获取的小方法。

如果您确切知道目标继承级别,那么当然更容易,因为您可以简单地替换

var superfun = this.constructor.prototype.constructor.prototype.getFuelConsumptionRate;

var superfun = EfficientCar.prototype.getFuelConsumptionRate;

请注意,javascript与您似乎更习惯的其他语言并不完全相同。尝试应用外来模式通常会导致程序更冗长,更灵活,维护更少。

答案 2 :(得分:0)

我是这样做的,当它不受支持时,使用Object.create()的垫片。

var Car = function() {
    // code
};

Car.prototype.getFuelConsumptionRate = function() {
    // code
};


var EfficientCar = function() {
    Car.call(this);
};

EfficientCar.prototype = Object.create(Car.prototype);

EfficientCar.prototype.getFuelConsumptionRate = function() {
    var result = Car.prototype.getFuelConsumptionRate.call(this)
    // code
};