给javascript加上 final 和 private 定义吧
前一段时间为了把backbone这个未完工的脚手架加工成一个全尺寸的框架,设计了一个叫做Stemcell的框架。但是javascript的灵活性,让框架的使用者在使用的过程中总会心惊胆颤,不知道什么时候会触碰了框架的底线(专业术语叫做G Spot),从而让系统处于“楼即将脆脆”的状态。
于是在实现Stemcell的过程中愈加感觉其他面向类的语言(面向类的语言不是面向对象的语言)中的种种呆板的特性现在竟然有点天然呆的可爱,所以昨天下午花了3个小时实现了一个小的基于javascript对象的 对象模型: Class.Model.js
它定义了如下几个特性:
- 一个BasicClass,认为所有从它派生出来的类都是继承自它
- 一个extend方法,便于继承
- 一个final字段的定义
- 一个private字段的定义
var Car = Class.new({ speed : null, color : null, initialize : function(args){ this.speed = args.speed; this.color = args.color; this.distance = args.distance; }, getHours : function(){ } })
var car = Car.new({ speed : "220KM", color : "black", distance : "128320KM" });
var Car = Class.new({ speed : null, color : null, initialize : function(args){ this.speed = args.speed; this.color = args.color; this.distance = args.distance; }, getHours : function(){ } })
var Car = Class.new({ speed : null, color : null, initialize : function(args){ this.speed = args.speed; this.color = args.color; this.distance = args.distance; }, getHours : function(){ this.hours(); } private : { hours : function(){ var distance = parseInt(this.distance); var speed = parseInt(this.speed); var hours = distance / speed; alert("I have been driven for " + hours + " hours"); } } })
var car = Car.new({ speed : "220KM", color : "black", distance : "128320KM" }); car.hours(); // 会抛出一个“找不到方法”的错误
var RaceCar = Car.extend({ brand : null });
Car.find = function(){ alert("looking for sth") } // 为Car类定义了一个类方法 find RaceCar.find() // -> 会弹出“looking for sth”
Car类有一个名为find的类方法,继承自Car的RaceCar 同样可以调用find方法。
final的定义
有时候我们希望框架的使用者在使用我们的框架时,不要因为继承而复写了我们父类中的方法,导致框架不可用,这时候非常需要javascript有类似final关键字,可以阻止这一惨剧的发生。
下面来看看Class.Model.js中final方法的定义,定义方法和private方法的定义类似,比如我们要给Car加上名为buzz的final方法,这个方法规定了车怎样鸣嘀,我们不希望不一样的车会有不同的鸣嘀方式,比如复写为“什么样的歌声才是最开怀”:
var Car = Class.new({ speed : null, color : null, initialize : function(args){ this.speed = args.speed; this.color = args.color; this.distance = args.distance; }, getHours : function(){ this.hours(); }, final : { buzz : function(){ alert("i can speed up to " + this.speed + " , and I'm " + this.color); } }, private : { hours : function(){ var distance = parseInt(this.distance); var speed = parseInt(this.speed); var hours = distance / speed; alert("I have been driven for " + hours + " hours"); } } })
将buzz方法的定义放在final字段中欧你,这样buzz方法就不能被子类复写了。
var RaceCar = Car.extend({ brand : null });
var car = Car.new({ speed : "220KM", color : "black", distance : "128320KM" });
car.buzz() // --> 将会弹出框显示 “i can speed up to 220KM , and I'm black”
var raceCar = RaceCar.new({ speed : "280KM", color : "red", distance: "311983KM" })
raceCar.buzz() // -> 会弹出类似的alert框
但是如果我们不小心在子类的定义中复写了buzz方法会怎么样呢?来看代码:
var RaceCar = Car.extend({ brand : null, buzz : function(){ alert("什么样的歌声才是最开怀!!!") } });
上面的RaceCar定义中重新定义了buzz方法,那么在js runtime运行到这个地方的时候会抛出一个异常:
如此,就可以保证父类中的final字段下定义的方法不会被子类复写了。
Class.Model.js定义的对象模型就是这样的,只提供了几个简单的特性,如果对这个东西感兴趣,可以到
https://gist.github.com/4441106
找到Class.Model.js的代码。
欢迎fork欢迎使用欢迎提出意见北京欢迎您