Groovy是动态的

使动态语言如此强大的原因是在表面上看来在运行时修改类的能力,例如,增加新的方法,但是,刚刚说到了,groovy类一次性产生并且在加载之后不能改变字节码,类不能改变,那么又怎么能增加方法呢?答案非常简单而又微妙。

Groovy类生成器生成的字节码必然不同于java编译器生成的字节码(不是在格式方 面,而是在内容方面),假设一个groovy文件包括一个像foo语句,groovy产生的字节码不是直接调用这个方法的,而是像这样:getMetaClass().invokeMethod(this, "foo", EMPTY_PARAMS_ARRAY)也就是说,方法的调用被重定向为通过对象的MetaClass进行处理,这个MetaClass 现在能在运行时处理如拦截、重定向、增加/删除方法等等之类的方法调用。

这个原则运用到所有通过groovy代码的处理,不管方法是否在groovy对象中或者在java对象中,记住,这没有区别。

动态代码的第二个选项是把代码放在一个字符串中并且通过groovy来运行它。一个字符串可以直接根据一定的逻辑进行构建,但是当心:可能你会被动态代码的复杂性吓到。

这里有一个构建两个字符串并且计算结果的例子:[code]
def code = '1 + ’
code += System.getProperty(‘os.version’)

//prints “1 + 5.1”
println code

//prints “6.1”
println evaluate(code)
[/code]注意代码是一个原始的字符串,这个字符串的内容为“1 + 5.1”,这是一个有效的groovy表达式(其实是一个脚本),替代一个程序员编写这个表达式(println 1 + 5.1),程序在运行时把它们放在一起,evaluat方法最后来执行这个语句。

等等——我们不是说一行一行的执行代码是不可能的,并且代码已经作为一个类被完整的构建了吗?这个代码怎么能执行?答案非常简单,还记得图2.7左边的路径吗?类能够在运行时生成,唯一的区别是输入的字符串也可以像*.groovy一样生成类。

根据代码的任意字符串来运行的能力是脚本语言的显著特征,这意味着groovy能像脚本语言一样使用,虽然groovy本身是一个一般的编程语言。