Groovy 延续了 java 的包结构中组织文件的方式,包结构用来在文件系统中找到相应的类文件。
由于*.groovy 源文件不需要编译成*.class 文件,因此在查找类的时候也需要查找*.groovy 文件,当这样做的时候,groovy 使用了相同的策略:编译器查找一个 groovy 类 Vendor 的时候,在 business 包对应的文件系统中查找 business/Vendor.groovy 文件。
在列表 7.2 中,我们在脚本代码有两个独立的类 Vendor 和 Address,如列表 7.11 显示的那样,并且把它们移动到了 business 包中。
类路径
查找类的时候是从某个地方开始的,java 的类路径就是基于这个目的来使用的,类路径是查找*.class 文件的开始点的一组列表。Groovy 查找*.groovy 时重用了类路径。
当我们查找一个给定的类的时候,如果 groovy 同时找到了一个*.class 和*.groovy 文件, 它使用最后修改的那个文件,也就是说,如果源文件在上一次编译之后做了修改,groovy 将重新编译源文件到*.class 文件。
包
事实上就像在 java 中一样,groovy 的类必须在定义之前指定它们所在的包,当没有声明包的时候,groovy 使用默认包。
列表 7.12 显示了文件 business/Vendor.groovy,这个文件中的第一行有一个包声明语句。
![]()
为了引用在 business 包中的 Vendor 类,你可以使用 business.Vendor 或者使用 import 语句导入类。
导入(import)
Groovy 跟随 java 的导入语句,在声明类之前进行导入。
注意:请记住这不像别的一些脚本语言,import 在字面上没有包含任何类或者文件,它仅仅是通知编译器如何来解析类的引用。
列表 7.13 显示了 import 语句的用法,使用.*标记通知编译器在 business 包中试图解析所有不知道的类引用。
![]()
注意:默认情况下,groovy 导入了 6 个包和两个类,这使得每个 g roovy 源代码程序看起来都包含了下面的初始化语句:[code]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
[/code]类型别名
import 语句有另外一个美妙的转变:可以与 as 关键字一起使用,这可以用来作为类型的别名,而一般的 import 语句运行使用类的名称来应用来,通过类型别名你可以使用任何你喜欢的名称来引用一个类,这个特性解决了类名称冲突的问题并且支持本地修改或者 bug 修复为一个第三方类库。
考虑下面的库类:[code]package thirdparty class MathLib {
Integer twice (Integer value) {
return value * 3 // intentionally wrong!
}
Integer half(Integer value) {
return value / 2
}
}
[/code]注意那个明显的错误(尽管一般情况下这不是一个错误而仅仅是一个本地想要的改变),假如现在我们有些已经存在的代码使用了这个类库:assert 10 == new MathLib().twice(5)我们能够使用类型别名来重命名原始的类,然后使用继承来修复它,不能修改原来已经使用的代码,如列表 7.14 显示:
![]()
现在,假设我们需要使用下面的额外的数学库:[code]package thirdparty2 class MathLib {
Integer increment(Integer value) {
return value + 1
}
}
[/code]虽然它在不同的包中,但是有一个与前面的类型相同的名称,如果不使用别名,那么我们在代码中必须有一个类使用全限定名称或者两个都使用全限定名称,通过别名,我们可以通过一种优雅的方式来避免这种情况,并且在我们的程序中通过为第三方类使用更好的别名也改善了交流,如列表 7.15 显示。
![]()
例如,如果我们后来发现一个 math 包 increment 和 tw ice/half 函数都应该有,我们能引用这个新库并且保留我们更有意义的名称。
在你的程序中应该考虑使用别名,甚至是在使用简单的内建类型的时候,例如,如果你开发一个冒险游戏,你也许需要将 Map 起一个名为 SatchelContents 的别名,这样不需要定义一个单独的 SatchelContents 的强类型,但同样提高了代码的易读性。