【问题标题】:Class Inheritance in Knockout with method overwrite具有方法覆盖的淘汰赛中的类继承
【发布时间】:2014-06-15 14:53:02
【问题描述】:

我正在尝试在 Knockout 中进行类继承以应用 DRY 原则,但还没有 非常成功。

我想要实现的是两种类型的服务器,它们具有一些相似之处,而无需重复代码或大量代码。

这是我最新的尝试,有些功能无法正常工作。

父类:

function BaseServer(options, builder) {

  this.formatted_price = ko.computed(function() {
    return utils.format_price(this.price(), options.prices.currency());
  }, this);

  this.drives = ko.observableArray([]);

  this.number_of_instances = ko.observable(1);

  // Not sure if this is a good approach for this problem
  for (i = 0; i < options.ssd.length; i++) {
    self.drives.push(new builder.ssd(options.ssd[i], options.prices));
  }
  for (i = 0; i < options.hdd.length; i++) {
    self.drives.push(new builder.hdd(options.hdd[i], options.prices));
  }

  // Will not work there is not this.cpu nor this.ram
  this.price = ko.computed(function() {
    var total = 0
    total += this.cpu.price();
    total += this.ram.price();
    total += _.reduce(this.drives(), function(mem, drive) {
      return drive.price();
    }, 0);
    return total;
  }, this);
}

我认为不对的地方:

  • 价格函数不起作用,因为父级无法访问 ram、cpu 变量。
  • 在我看来,builder 方法是一种非常奇怪的方法,但它确实有效。
  • 我在参数选项中传递函数,然后由类调用。

然后是孩子们。

function ServerGama(options){
  // Constructors for disks
  var builder = {
        ssd: SsdGama,
        hdd: HddGama
      },
      self = this;
  ko.utils.extend(self, new BaseServer(options, builder));

  // Normal attributes
  self.cpu = new CpuGama(options.cpu.up, options.cpu.down, options.prices);
  self.ram = new RamGama(options.ram.up, options.ram.down, options.prices);
}

function ServerBeta(options){
  var builder = {
        ssd: SsdBeta,
        hdd: HddBeta
      },
      self = this;
  ko.utils.extend(self, new BaseServer(options, builder));

  // Normal attributes
  self.cpu = new CpuBeta(options.cpu, options.prices);
  self.ram = new RamBeta(options.ram, options.prices);
  self.licenses = new server_licenses([
    {
      'name': 'Server 2008',
      'price': options.prices.cost_per_2008
    },
    {
      'name': 'Server 2009',
      'price': options.prices.cost_per_2009
    }
  ], options.prices.currency, options.choice);
  // This price does not seem to overwrite BaseServer price
  this.price = ko.computed(function() {
    // This will not work because we are losing the biding that price is making to the cpu, ram, disk variables
    var total = this.price.call(this);
    total += self.licenses.price();
    return total;
    }, 0);
  }, this);
}

我认为不对的地方:

  • 来自父级的 formatted_price 不会使用来自 BetaServer 类的这种覆盖。
  • 也许我可以用另一种方式构建磁盘

【问题讨论】:

    标签: javascript inheritance knockout.js overriding prototype


    【解决方案1】:

    如果我想要 js 中的“类”,我转向TypeScript

    class Drive {
        price = ko.observable(5);
    }
    
    class BaseServer {
    
        drives = ko.observableArray<Drive>([new Drive()]);
    
        price = ko.computed({
            owner: this,
            read: () => {
                return this.drives()[0].price();
            }
        });
    }
    
    class ServerGama extends BaseServer
    {
        price = ko.computed({
            owner: this,
            read: () => {
                return this.price() + 1;
            }
        });
    }
    

    TypeScript playground here

    这将编译成以下JS:

    var __extends = this.__extends || function (d, b) {
        for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
        function __() { this.constructor = d; }
        __.prototype = b.prototype;
        d.prototype = new __();
    };
    var Drive = (function () {
        function Drive() {
            this.price = ko.observable(5);
        }
        return Drive;
    })();
    var BaseServer = (function () {
        function BaseServer() {
            var _this = this;
            this.drives = ko.observableArray([new Drive()]);
            this.price = ko.computed({
                owner: this,
                read: function () {
                    return _this.drives()[0].price();
                }
            });
        }
        return BaseServer;
    })();
    
    var ServerGama = (function (_super) {
        __extends(ServerGama, _super);
        function ServerGama() {
            _super.apply(this, arguments);
            var _this = this;
            this.price = ko.computed({
                owner: this,
                read: function () {
                    return _this.price() + 1;
                }
            });
        }
        return ServerGama;
    })(BaseServer);
    

    http://jsfiddle.net/sjroesink/Pm6zq/

    【讨论】:

      【解决方案2】:

      这不会回答你所有的问题,但这里有一个我喜欢如何处理继承和覆盖方法的例子:

      var SuperClass = function(options) {
          var self = this;
      
          options = options || {};
      
          self.value = ko.observable(options.value);
      
          self.computed = ko.computed(function() {
              return self.value() + 100;
          });
      };
      
      var SubClass = function(options) {
          var self = this;
      
          // call super constructor
          self.constructor.call(self, options);
      
          // save method from super
          var super_computed = self.computed;
      
          // overwrite method on child class
          self.computed = ko.computed(function() {
              // use saved super method in the overwritten method
              return super_computed() + 5;
          });
      };
      SubClass.prototype = new SuperClass();
      
      var sub = new SubClass({ value: 1 });
      console.log(sub.computed()); // should be 106
      
      var sub2 = new SubClass({ value: 2 });
      console.log(sub2.computed()); // should be 107
      

      这是一个展示此方法的 JSFiddle:http://jsfiddle.net/szQRb/1/

      【讨论】:

      • 我必须试试这个。但它真的看起来像我正在寻找的东西。 Js 有很多关于如何构建类的资源,以至于很难找到一个明确的模式来解决常见问题。非常感谢查理。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 2012-11-20
      • 2012-10-22
      • 2012-09-27
      • 1970-01-01
      • 2013-03-27
      • 2014-10-08
      相关资源
      最近更新 更多