微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Unmi 学习 Groovy 之命名参数

Groovy 中提供了一个减少输入的特性叫做命名参数(Named Parameter)。GroovyBean 可以通过在构造器调用中传递冒号隔开的属性名称和值进行构建。如:


其实类似的用法早已有之,这有如 C++ 中的初始化成员列表,VB、Python、Transact-sql 中的命名参数,JavaScript 中的 JSON  写法,Ruby 中提供的 Syntax sugar用 hash 模拟所谓的 keyword argument。

我们先详细介绍 Groovy 的命名参数的用法与本质,然而再附上其他一些语言类似用法的实例,纵向贯通以加深印象。

要说从外部表现上好像是先调用了空构造方法,然后是相应的 setter 方法进行设值。因此,我们所直接想像的应该相当于下列 Java 代码


不过,假如你把 Groovy  生成的 class 文件反编译一下就会发现 Groovy 为上面那行生成了如下代码
 

所以若再加以试验,就会知道那个 Car 必须要有一个空的构造方法,这是必要条件。但它们的属性值如果有相应的 setter 方法就用 setter 方法赋值,如果没有就直接通过反射进行设值。所以并不要求属性有相应的 setter 方法,甚至是私有属性而无相应的 setter 方法也不打紧。即使只有一个光头的 setter 方法,无对应属性也是可以的。--有点啰嗦,觉得有用的话,可尽力去理解。

Groovy 是通过 org.codehaus.groovy.runtime.ScriptBytecodeAdapter 来完成这一过程的,看到 Bytecode 就知道它大概做了一些不光明的事情。

前面看到了,一行代码可以完成多行代码功能。迫不急切地,我们还是来点有实效性的东西,例如构造一个 JFrame 窗口:


对上面那样一个过程,我们可以一句话说完,简洁易懂。要领就在于你只要发现可用的属性(不管是私有的还是别的),或是 setXxx() 方法的那个 xxx (符合 JavaBean 规范即可) 就可以拿来作为命名参数的名字。

还应注意的是:在给 size 赋值时 size:[400,300] 使用到了隐式构造(Implicit constructors),size 原本接收的是一个 Dimension,而实质 [400,300] 就是隐式的调用了 new Dimension(400,300)。所以 location 属性也可以写成 [300,200]。隐式构造还常用于 Builder 中,如  SwingBuilder。

命名参数不仅可以应用于构造实例时,还能运用于普通方法调用上,而且这种机制了可以接受 Map 对象作为参数的方法

例如,前面的那么代码可以写成:


并且生成的字节码与原来完全一样,总之都是转换成对象数组,然后反射赋值。

再说一个接受 Map 参数的方法,以命名参数形式来调用的例子:


调用时可用以下两种形式,效果是完全一样的:


为有助于理解,还是反编译出以上两行生成的 Java 代码(都是一样的):


用 Map 的形式只适用于键是字符串的情况。

前面例子中的属性值都是字符串,其实是可以接受任何的属性类型,例如:


注意:前面的代码以都是在 Groovy 1.5.6 版本中测验过,以及这一版本生成的字节码;可能其他版本生成的字节码略有不同,但执行结果应不会有差异。


附录:(对比其他几个语言的命名参数用法)
这里只是说类似,但是千万要注意 Groovy  的命名参数不能像 VB/Python/Transact-sql 那样,调用方法时指示哪个参数是什么。Groovy 的命名参数是针对于类的属性(或者是 setter 方法)或 Map 的 Key。

1) C++ 的初始化成员列表:


2) VB 的命名参数:


3) Ruby 的做法:ruby 其实没有所谓的 keyword argument,而是提供一个Syntax sugar用 hash 模拟。


4) Transact-sql 中的命名参数:


其他像 Python、JavaScript 等各种语言的命名参数的用法就没必要继续列了。但据此我们能体验到这一特性确有其方便可取之处。

参考:1. 《Java 脚本编程,语言、框架与模式》第 4 章
        2. 《Groovy in Action》第 7 章 Dynamic object orientation,Groovy style
        3. C++初始化成员列表(member initialization list)
        4. Ruby慣寫法
        5. Python 使用可选参数和命名参数

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐