无聊+蛋疼, 试试用javascript怎样实现接口
时间:2010-08-27 来源:undefined
今天, 当当的书到了, 《javascript设计模式》。
刚刚翻了下, 上来就大谈特谈接口。
提到:javascript本身不支持接口, 所以有三种方法可以实现接口。
第一种是掩耳盗铃式的, 在类前面写注释:me要实现these方法, 请不要拦着我。。。
- -!
第二种是做属性检查。看的晕晕的。 似乎是, 写代码查, 你对不对?不对给我出局。
=。=
第三种是鸭子检查。说到底还是检查。 只不过放到类里面检查去了。 不全部实现, 连new都不行。
啊, 这下严格了。^_^
作者喜欢第三者(。。。。 表误会, 就是第三个的意思)。 我则喜欢第二者。
作者说第二个不好, 我琢磨着挺好的啊。
正好时间比较空, 我就试着写了一段检查程序用来查接口玩。
因为这不是在干什么好事, 所以我给对象命名为:
EvilJSLib
啊, 首先写了一堆定义接口和类的东东。
所以就是:
EvilJSLib.js
代码 (function(window, undefined){
var IInterFace = function(interfaceName){
this.interfaceDetail = {};
this.interfaceDetail.interfaceName = interfaceName;
this.interfaceDetail.properties = [];
this.interfaceDetail.methods = [];
};
var IClass = function(className){
this.classDetail = {};
this.classDetail.className = className;
this.classDetail.InterFaces = [];
};
IInterFace.prototype.AddProperty = function(name){
this.interfaceDetail.properties.push(name);
return this;
}
IInterFace.prototype.AddMethod = function(name){
this.interfaceDetail.methods.push(name);
return this;
}
IClass.prototype.implement = function(InterFace){
this.classDetail.InterFaces.push(InterFace);
}
var EvilJSLib = {
NameValuePair: function(){
this.name = '';
this.value = '';
},
CreateInterface: function(name){
return new IInterFace(name);
},
CreateClass: function(name){
return new IClass(name);
}
};
window.EvilJSLib = EvilJSLib;
})(window);
然后impletement就成了方法, 这样就避免了没有这个关键字的问题了。。。。
然后呢, 我写了个检查程序。 为了让这段小小的程序给自己强大的满足感, 我用了个很夸张的词:
compile!
当然了, 其实只是检查是不是所有的属性都实现了。
- -!
JSCompiler.js
var jsCompiler = {
ErrorCodes: {
'0x01': {
name: 'ClassNotImeplement',
detail: 'The Class is not Imeplement'
},
'0x02': {
name: 'PropertyNotDefined',
detail: 'The Property is not Imeplement'
},
'0x03': {
name: 'MethodNotDefined',
detail: 'The method is not Imeplement'
}
},
OutPutError: function(ErrorCode, ClassName, subNameType, subName){
var currentError = jsCompiler.ErrorCodes[ErrorCode];
document.writeln('ErrorCode:' + ErrorCode);
document.writeln('<br />');
document.writeln('\tname:' + currentError.name);
document.writeln('<br />');
document.writeln('\tdetail:' + currentError.detail);
document.writeln('<br />');
document.writeln('\tClass Name:' + ClassName);
document.writeln('<br />');
document.writeln('\t' + subNameType + ' Name:' + subName);
document.writeln('<br /><br />');
},
ValidateAllInterfaceImplemented: function(Class, Interface){
document.write('<hr />');
for (var i = 0, length = Interface.interfaceDetail.properties.length; i < length; i++) {
var currentItemName = Interface.interfaceDetail.properties[i];
if(!Class.propertyIsEnumerable(currentItemName) || typeof Class[currentItemname] == 'function'){
jsCompiler.OutPutError('0x02', Class.classDetail.className,'Property',currentItemName);
}
}
for (var i = 0, length = Interface.interfaceDetail.methods.length; i < length; i++) {
var currentItemName = Interface.interfaceDetail.methods[i];
if(!Class.propertyIsEnumerable(currentItemName) || typeof Class[currentItemname] != 'function'){
jsCompiler.OutPutError('0x03', Class.classDetail.className,'Method',currentItemName);
}
}
document.write('<hr />');
},
compile: function(Class){
for (var i = 0, length = Class.classDetail.InterFaces.length; i < length; i++) {
jsCompiler.ValidateAllInterfaceImplemented(Class, Class.classDetail.InterFaces[i]);
}
},
compileAll: function(classes){
for (var i = 0, length = classes.length; i < length; i++) {
jsCompiler.compile(classes[i]);
}
},
};
window.EvilJSLib.jsCompiler = jsCompiler;
})(window);
然后就是使用了。
我试着写了这么个文件来测试下EvilJSLib:
TestEvilJsLib.js
代码 (function(EvilJSLib){
var TestEvilJSLib = {};
var IList = EvilJSLib.CreateInterface('IList');
IList.AddProperty('name').AddProperty('age').AddMethod('printname');
TestEvilJSLib.IList = IList;
var List = EvilJSLib.CreateClass('List');
List.implement(IList);
TestEvilJSLib.List = List;
window.TestEvilJSLib = TestEvilJSLib;
})(window.EvilJSLib);
这样呢, 我们创建了一个接口, 叫IList, 创建了一个对象叫List, 实现了接口, 但是什么都没写。
毫无疑问, 这是不允许的, 这要是C#, 编译错误都够装满整个外滩了。
那么如何知道这些问题呢?
当然了, 调用我们的编译器吗!
简单的这样:
代码 <html>
<head>
<title>only debug</title>
<script type="text/javascript" src="lib/EvilJSLib.js"></script>
<script type="text/javascript" src="lib/TestEvilJSLib.js"></script>
<script type="text/javascript" src="lib/JSCompiler.js"></script>
<script type="text/javascript">
window.EvilJSLib.jsCompiler.compile(window.TestEvilJSLib.List);
</script>
</head>
</html>
OK, 运行出来了一个看起来很威武的结果:
ErrorCode:0x02
name:PropertyNotDefined
detail:The Property is not Imeplement
Class Name:List
Property Name:name
ErrorCode:0x02
name:PropertyNotDefined
detail:The Property is not Imeplement
Class Name:List
Property Name:age
ErrorCode:0x03
name:MethodNotDefined
detail:The method is not Imeplement
Class Name:List
Method Name:printname
嘿嘿, 这下就可以一目了然哪些类实现了接口但是没有完成方法了。
至于这样做有什么好处。。。 这个, 大概可以模拟一些设计模式吧。 策略模式毫无疑问是没问题的。 因为对于js来说, 同名的方法, 就是同一个方法。。 用名字调的, 一定是最终实现的。
如果有继承怎么办? 不是有prototype来处理么。 一层一层跌落。 自然会运行的很好的。
声明:这本来就是一篇蛋疼的文章, 只用于娱乐, 严禁正式使用。
最后我想说:在你进来读这篇文章的第一个字的时候,你就上当了。。。。。
而且我必须黑幕掉沙发。