Groovy 方法和参数

方法的声明与你看到的变量的声明有相同的概念:通常能使用 java 修饰符;返回类型的声明是可选的;如果没有修饰符或者返回类型,那么使用 def 关键字来填空白,当使用 def 关键字的时候,方法的返回类型被认为是没有类型(尽管没有返回类型,这时与 vo id 方法 等价),在这种情况下,groovy 将方法的返回类型定义为 java.lang.Object,缺省的方法访问范围为 public。

列表 7.5 通过例子的自我描述方式显示了方法声明的典型用法。

在(1)处,main 方法有些有趣的改变,首先,pub lic 修饰符能够忽略,因为方法声明的默认修饰符就是 public;其次,为了使 main 方法的启动执行 args 通常的类型为String[]。

感谢 groovy 的方法分派,不管如何工作,尽管 args 目前的类型隐式为 jav a.lang.Ob ject。

第三,方法分派时由于返回类型没有使用,我们能够进一步忽略 void 的声明。

因此,这是 java 的声明:public static void main (String[] args)在 groovy 中浓缩为:static main(args)注意:如果在 main 方法的返回语句中声明了返回类型的话,将通不过 java 编译器的检 查,在 groovy 中,返回语句是可选的,因此编译器偶然检查到没有返回类型是不可能的。

main 方法的例子说明了显式声明参数的类型是可选的,当声明类型被忽略的时候,groovy 使用 Object 作为类型,可以顺序的使用多个参数,通过逗号进行分隔,列表7.6 显示了显式的声明参数类型和忽略参数类型是可以混合在一起使用的。

在迄今为止的例子中,所有方法调用都与方法参数的位置有关,这意味做每一个参数已经根据它参数列表中的位置被决定了,这是容易理解的,并且便于简化你已经看到的案例,但对于复杂的脚本有一些痛苦的缺点:

 你必须记住真实的参数的顺序,当参数列表比较长时这增加了难度;

 对于非传统的脚本使用,如果根据不同的信息调用方法很有意义,那么需要构建许多不同的方法来处理这些差异,这很快就变得笨重起来并且导致方法的难以维护,
特别是当有些参数是可选的时候,如果许多可选的参数具有相同的类型,这会变得特别困难。

幸运的是,groovy 使用 map 作为一个命名参数列表来拯救了这种情况。

注意:每当谈论到命名的参数的时候,我们的意思是 map 的 key 在方法中被用作参数 被调用,从一个程序员的视角看,这看起来就像原生的命名参数的支持,但其实不是这样的,这种技巧是必须的,因为 JVM 不支持把参数的名称保存在字节码中。

列表 7.7 介绍了 groovy 支持的位置参数和命名参数的方法定义和调用,可变长度的参 数列表,可选的参数和其默认值,例子提供了四种组合,每一种都突出了不同的调用方法途径。

这四种方案都都有他们的优点和缺点,在(1),sumWithDefau lts,我们为方法调用有了大多数明显期望的参数声明,这满足了简单脚本的需要——能够增加 2 个或者 3 个参数在一起,但是这种方式受到已经声明的参数的限制。

如(2)这样在 groovy 中使用 list 是非常容易的,因为在方法调用中,参数仅仅放置在 方括号中,我们也可以支持任意长度的参数列表,不管怎样,方法参数的意义不能明显的表 示出来,因此,这个方式最适合于所有参数都有相同的意思的情况,在这里对参数列表进行了累加,参考 4.2.3 节来了解 List.inject 方法的详细信息。

在(3)的 sumWithOption als 方法可以通过 2 个或者更多的参数进行调用,声明了这样一个方法,定义最后一个参数为一个数组,groovy 动态方法分派将剩余的参数打包进这个数组中。

命名参数的支持通过(4)的方式进行支持,在使用他们之前设置所有错过的值为一个默认值是一个好的实践。这也较好的显示出 key 将被用在方法体中,因为这明显不是通过方法声明得到的。

当设计你的方法的时候,你必须从可选方案中选择一个,你也许希望把你的代码通过文档的形式记录到项目中,或者还包括了 groovy 的代码风格。

注意:实现可变长度的参数列表的第二种方式是,你可以覆盖 groovy 的分派方法invokeMethod(name,params[]),这是每个 GroovyObject 对象都提供的方法,在 7.6.2 将学习到这方面的更多知识。

高级命名

当在对象引用上调用一个方法的时候,我们通常使用下面的格式:objectReferenct.methodName()这种格式受到 jav a 方法命名的格式限制;例如,它们不能包含特殊的如减号(-)或者点号(.)这样的字符,不管怎样,如果你把方法名称放在引号中,那么 groovy 允许你在方法名称中使用这样的字符:objectReferenct.’my.method-Name’()这个特性的目的是支持把调用方法的名称变成函数的一部分,通常情况下不直接使用这个特性,但是 groovy 的其他部分将使用到这个特性,在第八章和第十章将看到这个特性的使用。

说明:有一个字符串,通常是使用 Gstring,如果这样 obj."${var}"()会怎么样,是的,这样是可以的,并且 Gstring 将被用来确定调用的方法的名称。

这些就是类成员的基本原理,在结束这个主题之前,通过引用对象引用到对象的一个成员的时候有一个便利的操作符是应该介绍的。