FAQ —— Groovy & Grails(更新于2007.06.25)
Q: 什么是闭包(Closure)?
A: 我们可以把closure简单地理解为语句块,下面让我们来看一下方法声明和closure定义的相似点:
方法声明:
def sayHello(name) {
println name
}
sayHello( " 山风小子 " )
println name
}
sayHello( " 山风小子 " )
closure定义:
def sayHello
=
{ name
->
println name
}
sayHello( " 山风小子 " )
println name
}
sayHello( " 山风小子 " )
通过代码比较,大家看出相似点了吧。
closure比方法更灵活,可以作为参数传入方法(这点类似于C++中的方法指针),而方法比如本例中的sayHello方法可以通过.&操作符来获得方法闭包
def sayHello(name) {
println name
}
def sayHelloMethodClosure = this . & sayHello
sayHelloMethodClosure( " 山风小子 " )
def hello(c) {
c("Daniel")
}
hello(sayHelloMethodClosure)
println name
}
def sayHelloMethodClosure = this . & sayHello
sayHelloMethodClosure( " 山风小子 " )
def hello(c) {
c("Daniel")
}
hello(sayHelloMethodClosure)
所以在Grails中大量的使用clsoure。
Q: ?.是什么
A: ?. 是‘安全引用符’,举例来说:
在Java中,为了程序的鲁棒性(robust),在对一个对象进行操作之前,我们会判断它是否为null
if
(
null
!=
obj) {
obj.doSomething();
}
obj.doSomething();
}
而在Groovy就方便多了,您可以用?.来达到上面的目的
obj
?
.doSomething()
等价于
obj
==
null
?
null
: obj.doSomething()
如果obj为null,则obj?.doSomething()的结果为null,否则就正常执行与Java无异:)
实例:
def obj
=
null
println obj ? .hello() // 打印出null
由于obj为null,所以就不执行hello(),即便obj中没有定义hello这个方法也不会报错 :)
println obj ? .hello() // 打印出null
Q: it是什么?
A: 如果您没有在Groovy的Closure中定义任何变量,那么Groovy会自动帮您定义一个it变量。
举例来说:
//
此处的a为自己定义的变量
def c = { a ->
println a
}
c( " Hello, world " )
def c = { a ->
println a
}
c( " Hello, world " )
注意上下两段代码的区别,下面的Closure没有定义任何变量,当要引用传入的参数时,用it来表示
//
此处的it是Groovy自动帮我们定义的变量
def c = {
println it
}
c( " Hello, world " )
def c = {
println it
}
c( " Hello, world " )
Q: @Property是什么?
A: 这是以前旧版Groovy的写法,用来定义成员变量,但由于大家反应它太丑了,所以在Groovy1.0+中已不建议使用,请用def替代它。
Q: 如何定制closure的字符串表示?
A: 定制类的字符串表示一般是通过重写(override)toString方法来完成的:
class
A {
String toString() {
" I am A "
}
}
def a = new A()
println " $a "
String toString() {
" I am A "
}
}
def a = new A()
println " $a "
但定制closure的字符串表示,则稍微特殊一点,是通过it << "closure的字符串表示",
在Groovy1.1中,"$closure"会将StringWriter的一个实例传给closure的隐式变量it,并引起closure的执行
如果仅仅是closure()的话,并不会有StringWriter实例传给closure的隐式变量it
def c
=
{
println " closure is executed. "
// 将这条语句看作toString方法就可以了,注意要使用if (it) {}来判断一下 :)
if (it) {
it << " I am a closure c "
}
}
println " $c "
println " closure is executed. "
// 将这条语句看作toString方法就可以了,注意要使用if (it) {}来判断一下 :)
if (it) {
it << " I am a closure c "
}
}
println " $c "
结果如下所示,闭包c先被执行,然后才执行println打印出closure的字符串表示
closure is executed.
I am a closure c
I am a closure c
Q: 出现在闭包中的owner是什么?
A: owner其实就是‘拥有’此闭包的一个对象,举例来说:
class
A {
def c = {
println " c's owner: $owner "
if (it) {
it << " closure c "
}
def innerC = {
println " innerC's owner: $owner "
}
}
String toString() {
' class A '
}
}
def a = new A()
def innerC = a.c()
innerC()
运行结果:
def c = {
println " c's owner: $owner "
if (it) {
it << " closure c "
}
def innerC = {
println " innerC's owner: $owner "
}
}
String toString() {
' class A '
}
}
def a = new A()
def innerC = a.c()
innerC()
c's owner: class A
c's owner: class A
innerC's owner: closure c
c's owner: class A
innerC's owner: closure c
Q: 为什么Grails比Rails更适用于企业应用?(摘自《 对Grails之误解 》)
A: 原因很多,最显著的两个原因就是Spring和Hibernate。到目前为止,有不计其数的组织在采用Spring和HIbernate,他们都有既有的Spring上下文环境,以及已经构造好的Hibernate领域对象等。
在我开始参与Grails项目之前,我就经历过同样的情况。我们设计Grails的目的就是为了让它和这些框架尽可能无缝地整合起来。因此,我们打个比方,你可以把一个用Java编写的Hibernate领域模型及其对应的配置文件直接扔进Grails应用中,然后就可以使用动态的查询方法,并且直接使用GORM了。
此外,Grails控制器使用了标准的Servlet API对象(如request、response和session等),因此可以和其它的Servlet一起使用。毕竟,掀起它的盖头之后,我们会发现它不过是一个Spring MVC应用。另一方面,Rails几乎是按照和EJB2一样的方式设计的(在我发现这点时,怎一个“震惊”二字了得!)。也就是说,你在扩展 ActiveController和ActiveRecord等框架对象时,你也就被绑定在了这套框架上。
在Rails里面根本就不存在领域模型的说法,Rails的模型就是数据库表。这当然是一件好事了,但在企业内部,同一个领域模型可能会在许多不同的应用中服用,比如说桌面应用和Web应用。在Java里,这实际上是非常成熟完善的,通过把类对象及相应映射文件打包成一个JAR文件即可。
Q: 用Grails开发的Web应用如何进行部署?
A: 执行‘grails war’将Web应用打成war包,然后就可以将应用部署到任何符合J2EE规范的Web服务器上了。
To be continued...
附: 朝花夕拾——Groovy & Grails