Groovy语言规范之程序结构
前言: 1.包名 Package names这里的包名同Java中的包名发挥着同样的角色。包名允许我们分隔代码从而避免冲突。Groovy类必须在定义之前指定他们的包,并且假设默认的包名存在。 // defining a package named com.yoursite package com.yoursite 你可以调用Foo类使用com.yoursite.com.Foo,当然下面也将介绍import声明的方式引用类。 2.导包 Imports为了引用任意一个类,而不需要包名。Groovy遵从了Java的方式允许使用import声明来解决类的导入。 // importing the class MarkupBuilder import groovy.xml.MarkupBuilder // using the imported class to create an object def xml = new MarkupBuilder() assert xml != null 2.1. 默认导入 Default imports默认导入时Groovy语言默认导入的。例如下面的代码: new Date() 同样的代码在Java中则需要导包声明:java.util.Date。Groovy默认为你导入了这些类。 import java.lang.* import java.util.* import java.io.* import java.net.* import groovy.lang.* import groovy.util.* import java.math.BigInteger import java.math.BigDecimal 之所以这样做,是因为这些类非常常用。通过默认导入,减少了代码量。 2.2. 简单导包 Simple import简单导包是你使用类的全路径进行导包。例如下面: // importing the class MarkupBuilder import groovy.xml.MarkupBuilder // using the imported class to create an object def xml = new MarkupBuilder() assert xml != null 2.3. 星号导入 Star import像Java一样,Groovy提供了一个特殊的方式导入包下的所有的类通过使用*,也就是所谓的星号导包。实行星号导包前的导入方式: import groovy.xml.MarkupBuilder import groovy.xml.StreamingMarkupBuilder def markupBuilder = new MarkupBuilder() assert markupBuilder != null assert new StreamingMarkupBuilder() != null 使用星号导包后: import groovy.xml.* def markupBuilder = new MarkupBuilder() assert markupBuilder != null assert new StreamingMarkupBuilder() != null 2.4.静态导包 Static import在Groovy的静态导包允许你导入类之后可以向静态方法一样在你自己的类中。和Java的静态导入相似,但是在Java1.4之上才能正常工作。 import static Boolean.FALSE assert !FALSE //use directly,without Boolean prefix! 2.5.静态导包别名 Static import aliasing这种用法比较类似于C语言中的typedef的用法。 import static Calendar.getInstance as now assert now().class == Calendar.getInstance().class 这样变得非常简洁易读。 2.6.静态星号导入 Static star import星号静态导入和规则的星号导入很相似。将会导入该类的所有的静态的方法。 例如,下面的例子: import static java.lang.Math.* assert sin(0) == 0.0 assert cos(0) == 1.0 2.7 别名导入 Import aliasing使用别名,我们可以使用自定义的名称来指向一个完全的类。同上,可以通过as关键字来实现。 package thirdpartylib public class MultiplyTwo { def static multiply(def value) { return value * 3 //intentionally wrong. } } 假如我们这样使用这个库: def result = new MultiplyTwo().multiply(2) 现在假设有这样一种情况,在使用了这个第三方库并且贯穿了你所有的代码,我们发现它没有给出一个正确的结果。我们怎样在一处修改,而不是修改源码,而不改变其他使用的地方?Groovy提供了简洁的方案。 import thirdpartylib.MultiplyTwo as OrigMultiplyTwo class MultiplyTwo extends OrigMultiplyTwo { def multiply(def value) { return value * 2 // fixed here } } // nothing to change below here def multiplylib = new MultiplyTwo() // assert passes as well assert 4 == new MultiplyTwo().multiply(2) 这就是通过as关键字重命名导入的类解决了这个问题。 3.脚本vs类 Script versus classes3.1. public static void main vs 脚本 public static void main vs scriptGroovy同时支持class和script(即类和脚本)。使用一下代码作为例子: class Main { //定义一个Main类,名字是任意的 static void main(String... args) { println 'Groovy world!' } } 你会发现以上是Java中的典型代码,代码嵌入类中执行。而Groovy是的这些变得更加容易,以下代码是等价的: println 'Groovy world!' 你可以把脚本想象成是一个不用声明的类。 3.2 脚本类 Script class脚本总是会被编译成类。Groovy编译器会为你编译这个类,会把脚本体复制进run方法。上面的例子会被编译如下: import org.codehaus.groovy.runtime.InvokerHelper class Main extends Script { //Main类继承了groovy.lang.Script类 def run() { //groovy.lang.Script需要run方法返回一个值 println 'Groovy world!' } static void main(String[] args) { //自动生成 InvokerHelper.runScript(Main,args) } } 如果脚本是一个文件,文件的基本名称会被用于生成脚本类。在这个例子中,如果文件名是Main.groovy,之后脚本类的会被命名为Main。 3.3. 方法Methods定义方法在脚本中是可以的,如下: int fib(int n) { n < 2 ? 1 : fib(n-1) + fib(n-2) } assert fib(10)==89 你可以将方法和代码混合。生成的脚本类会将所有的方法带入脚本类,并且嵌入所有的脚步体到run方法中: println 'Hello' //脚步开始处 int power(int n) { 2**n } //一个没有脚本体的方法 println "2^6==${power(6)}"//脚本 以上代码会被转化成: import org.codehaus.groovy.runtime.InvokerHelper class Main extends Script { int power(int n) { 2** n}//power方法被复制进了自动生成的脚本类里面 def run() { println 'Hello' //脚本被复制到了这里面 println "2^6==${power(6)}" } static void main(String[] args) { InvokerHelper.runScript(Main,args) } } 尽管Groovy通过你的脚本创建了一个类,不过这个类对用户来说依然是易懂的。特别的,脚本被编译成字节码,行号被保留。这就意味着如果脚本中出现了一个异常,异常记录将会返回相应的原始脚本的行号,而不是你自动生成类的行号。 3.4. 变量Variables变量在脚本中不需要类型声明。这就意味着,如下脚本: int x = 1 int y = 2 assert x+y == 3 等同于: x = 1 y = 2 assert x+y == 3 然而,二者之间在语义学上是不同的,表现如下:
如果你希望变量变成一个类的字段而不是在Binding中,你可以使用@Field annotation. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |