您的位置:首页 > 其它

动态语言的动态绑定的实现机制, 以及改进

2008-01-18 09:31 274 查看
大家应该知道了c++等语言的virtual, 引入的动态机制, 是用一个 vritual table 来实现的. 做了一个间接的跳转, 而不是编译器静态的绑定. 这个动作, 使得OO的根本所在, 世界变得十分精彩.

但是, 动态语言里面, 就不是这个样子了. vtbl中, 是通过偏移来做到动态绑定的, 这一点很有趣. 也会出现一些很艰难的bug.

比如, 有一回, 有位兄弟把一个过去编译的的动态库扔出来一个接口, 给现在的程序调用, 而这个头文件已经修改过了.
然后就发生了无法理解的跳转, 明明调用的是apple(), 结果就是发生了orange()... 把我折腾的死去活来, 最后才想到这个问题.

这也是com的开发中, 无数次的警告. com接口只可以增加, 不能修改. 其实, 连修改一下顺序都是不允许的.

好, 言归正传, 说道动态语言了.

动态语言, 与静态类型的一个最根本的差别就是, 无类型. 动态语言的哲学就是: 因为你可以亮, 所以亮; 而静态语言是, 因为你是一个灯, 所以可以亮.

动态语言不再根据类型来决定哪个vtbl, 没有类型之后, 就只能使用dict, 来记录函数的名字.
例如: a.light() 就会到a的属性中查找是否有light这个入口, 有则执行, 无则报错.

这样, 很多东西就变得简单了. 需要一个啥, 就给他配一个啥. 有点按需分配的意思了. 所以, 动态语言在集成方面有着先天的优势, 做很多事情非常简单, 所以, 事实也证明了, 生产效率比静态语言高约 8~10倍.
这才是动态语言的根本意思, 而其他的什么丰富的库, 内存管理等等, 都只是添头而已, 锦上添花, 让动态语言更加好用.

当然也有一个问题, 如果每一个对象里面都记录这么一大套, 是不是有点太浪费了. 性能上会有很大的影响, 这个是毫无疑问的. 所以, 比较好的做法就是和c++一样, 做一个虚函数表. 但是这个表是一个dict, 记录了调用的名字, 这样就完成了. 其性能上的差异就是, c++直接根据偏移得知 *(vtbl + offset) 函数地址, 进行调用. 动态语言根据 vtbl[funcname] 进行调用. 所以 dict就是动态语言的核心了, 他的算法上的要求就非常高, 咽喉所在, 是一切的瓶颈. 如果有人能把hash算法提高1%, 他就是神.

这里我们可以看出来一个缺陷, 就是动态语言无法支持overload. 大家可以看c++的overload 是如何实现的, c++和c是编译兼容的. 所以内部实际还是c的方式, 把this指针通过编译前端, 编译成c代码, 后端还是可以用c的编译器完成. (呵呵, 实际并非如此, 但大致可以这么理解)

linux可以用nm, windows下面可以用dumpbin 看obj文件或者运行文件, 会看到很多#!@$#^%#&&* , 头晕了.
就是说, 一个函数对应的符号, 并不是直接过去的, 而是做了一个编码, 这个编码就是用来实现overload 和类的规划了. 编码中有类名, 函数名, 参数类型, 从而唯一确定了一个方法.

如果没有c++, 用c来实现的话, 我们总是通过前缀, 后缀来的方式, 用编码规范的方式来定义函数, 大家都很熟悉了. 不论linux世界还是windows世界, 尤其是微软的API, 都是这一点的严格执行者. 非常华丽, 非常壮观.

大家可以看到, 很明显得出这么一个结论:
动态语言中,没有类型, 而且还是通过函数名称来实现vtbl的, 就先天从机制上就无法支持overload... 很不幸事实就是这样的. 看python, 就知道了. 没有overload...所以在jython或者ironpython对java平台和.net平台无缝连接的时候, 还是有一点点瑕疵的. 就是不支持overload.... 对此, 我们表示非常遗憾, 大家可以去参考一下ironpython的实现代码, jython也是参考了ironpython的方式.

好, 现在我来提一个改进的想法. 能稍微挽回一点点面子. (呵呵, 如果说了那么多机制, 没有说建议, 就白讲了)
动态语言没有类型, 这是最大的优势, 无法解决, 但是参数的数量还是能够确定的. 可以用编码或者metadata的方法, 记录参数的个数. 然后调用的时候, 根据个数不同来做到一定程度的overload...

overload 的作用还是比较大的, 可以一定程度上客服程序言的词汇匮乏. 避免了程序中制造怪异名字, 天数单词的问题.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: