【问题标题】:Inheritance: How to emulate super.method inside overriden method继承:如何在被覆盖的方法中模拟 super.method
【发布时间】:2013-01-14 12:49:37
【问题描述】:

我正在尝试以最简单的方式实现继承。我知道 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 classes,对不起,函数。

【问题讨论】:

  • 不认为这是最好的做法,但 return Car.prototype.getFuelConsumptionRate() / 2 应该可以工作
  • @VeXii 不,浏览器说Car.prototype.getFuelConsumptionRate 不是函数。
  • 这个相关问题(不是重复的)可能有用:stackoverflow.com/questions/13359363/…

标签: javascript inheritance overriding


【解决方案1】:

如果你想在 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

【讨论】:

    【解决方案2】:

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

    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 与您似乎更习惯的其他语言并不完全相同。尝试应用外来模式通常会导致程序更冗长、更不灵活且更难维护。

    【讨论】:

    • 感谢您的回答。这行得通。仍然有一些我无法理解的东西:在Car“类”中,run 函数调用this.getFuelConsumptionRate,但该函数不是在 Car 中定义的,而是在 Car.prototype 中定义的。为什么它不抛出错误?
    • 因为在 javascript 中函数是“一等公民”。您可以使用callapply 以任何对象作为上下文来调用函数。您实际上并没有在对象上定义函数:您定义了一个函数,然后将其分配为对象属性的值。
    • 我的意思是为什么在run函数中我们可以使用this.getFuelConsumptionRate而不是this.prototype.getFuelConsumptionRate。我不记得如果一个对象没有成员,它会被转发到原型。
    • @MisterSmith 见this related answer
    • 再次感谢。不管怎样,这种方法太老套了。 constructor.prototype.constructor.prototype 组合对我的眼睛造成的伤害比在主要的“构造函数”块中添加几行还要多。我已经重构了我的代码以坚持 JS 传统的基于原型的方法。你说得对,我不应该这样对抗语言。
    【解决方案3】:

    我就是这样做的,在 Object.create() 不受支持时使用 shim。

    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
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 1970-01-01
      • 2021-11-30
      • 2014-08-21
      • 2013-04-25
      • 2015-10-07
      • 2012-11-20
      相关资源
      最近更新 更多