我试图在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);
}
我认为错误的事情:
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);
}
我认为错误的事情:
答案 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;
}
});
}
这将编译成以下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);