sri*_*ram 2 compiler-construction groovy static dynamic
我为静态类型语言构建了一个小型编译器。在了解了静态语言的工作原理之后,我很难理解像 Groovy 这样的动态语言。
在构建我的编译器时,我知道一旦生成机器级代码,就无法更改它!(即它的run-time)。
但是 Groovy 是如何做到这种神奇的事情的,比如在如下语句中推断类型:
def a = "string"
a.size()
Run Code Online (Sandbox Code Playgroud)
就我而言,groovy 必须在运行该行之前找到a类型。看起来它是在编译时(构建 AST 时)这样做的!但这种语言被称为动态的。stringa.size()
我很困惑,请大家帮我解答一下。
谢谢。
Groovy 并不简单地“调用”方法,而是通过元对象协议调度它。方法调用作为消息发送到对象,对象可以响应也可以不响应。使用动态类型时,对象类型并不重要,只要它响应该消息即可。这称为鸭子打字。
当您反编译 Groovy 代码时,您可以看到它(尽管不容易)。您可以groovyc使用其他工具进行编译和反编译。我推荐jd-gui。由于 Groovy 的方法缓存,您不会看到该方法被显式调用(这样做是为了实现 Groovy 的简洁性能)。
对于一个简单的脚本,例如:
def a = "abcdefg"
println a.substring(2)
Run Code Online (Sandbox Code Playgroud)
这将是生成的代码:
CallSite[] arrayOfCallSite = $getCallSiteArray(); Object a = "abcdefg";
return arrayOfCallSite[1].callCurrent(
this, arrayOfCallSite[2].call(a, Integer.valueOf(2))); return null;
Run Code Online (Sandbox Code Playgroud)
并且方法调用是“分派”给对象的,而不是直接调用。这与 Smalltalks 和 Ruby 方法调度类似。正是由于该机制,您可以拦截 Groovy 对象上的方法和属性访问。
从 Groovy 2 开始,Groovy 代码可以静态编译,因此就像编译器一样。