使用方法覆盖在Knockout中的类继承

时间:2014-04-29 15:08:44

标签: javascript inheritance knockout.js override prototype

我试图在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);
}

我认为错误的事情:

  • Price函数不起作用,因为父级无法访问ram,cpu变量。
  • 构建器方法在我看来是一种非常奇怪的方法来实现这个结果,但它确实有效。
  • 我在参数选项中传递函数,然后由类调用。
然后是孩子们。

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类中的覆盖。
  • 也许我可以用另一种方式构建磁盘

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:1)

如果我想要&#34;班级&#34;在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/