加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

【转】Groovy++:与Groovy有何不同

发布时间:2020-12-14 17:06:16 所属栏目:大数据 来源:网络整理
导读:1.Groovy++编译时检查更严格 例1: /* Leave it commented to run the dynamic Groovy version; Uncomment to run Groovy++ version *///@Typedpackage testdef x = { List list - list.size()}x(1) 对Groovy,上述代码编译不会出错,但运行时会出错。因为我

1.Groovy++编译时检查更严格

例1:

/* Leave it commented to run the dynamic Groovy version; 
    Uncomment to run Groovy++ version */
//@Typed
package test

def x = { List list ->
    list.size()
}

x(1)

对Groovy,上述代码编译不会出错,但运行时会出错。因为我们调用的是x(Integer),而定义的是x(List)。

对Groovy++,编译时即报错:"Cannot find method { List -> ...}.doCall(int)"。

例2:

/* Commented -> dynamic Groovy version; 
    Uncommented -> Groovy++ version */
//@Typed
package test

class Foo {
    def greet() {println "Foo says hello"}
}

class Bar {
    def greet() {println "Bar says hello"}
}

def c = {greeter -> greeter.greet()}

c(new Foo())
c(new Bar())

对Groovy,得益于duck-typing,上述代码编译时和运行时都不会出错。

对Groovy++,则会出错:"Cannot find method Object.greet()" ,因为它会依照闭包参数的静态类型来做判断。

2.通过ExpandoMetaClass即时修改类型。

例3:

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */
//@Typed
package test

String.metaClass.foo = { ->  println "foo called" }
"".foo()  /* call my new method */

对Groovy,上述代码运行得很好,并动态给String增加foo方法。

对Groovy++,静态模式下不支持这一特性,“Mixed”模式可以解决这一问题,既享用动态特性,又保持静态检查。如下例所示

例4:

@Typed(TypePolicy.MIXED)
package test

String.metaClass.foo = { ->  println "foo called" } // supported

"".foo()

3.Groovy++闭包更像是Java的内嵌类

在Java中,内嵌类不能引用其外部范围的非final成员。如下述代码编译将出错。

例5:

void foo(){
    String data = "";
    class Inner {
        void innerFoo() {
            System.out.println(data);
        }
    }
}

groovy把闭包看作是内嵌类,但是不限制对外部非final成员的访问,因此下属代码可以在Groovy中运行

例6:

void foo(){
    String data = 'original';
    def cl = {data = 'changed'} // access non-final data of its outer scope
    cl()
    assert data == 'changed'
}

foo()

Groovy++与Java更加接近,只允许以只读方式访问非final数据成员。如下例,如果试图修改这些成员,则会报 错:"Cannot modify final field test.Test$foo$1.data"

例7:

@Typed
package test

void foo(){
    String data = 'original';
    def cl = {data = 'changed'}
}

foo()

之所以这样,项目领导Alex Tkachman解释主要是避免并行运行风险。但如果不做并行运算,是否有什么解决之道?参见下例,用groovy.lang.Reference:

例8:

@Typed
package test

void foo(){
    Reference data = ['original']
    def cl = {data = 'changed'} // now even Groovy++ supports modification of non-final outer scope data
    cl()
    assert data == 'changed'
}

foo()

4.Groovy++不再直接访问私有成员

Groovy没有限制从外部访问一个类的私有成员,下例将正常运行。

例9:

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */
//@Typed
package test

class SecretService {
    String secret = "secret"
    String getSecret() {
        "covered-" + secret
    }

    private launchOperation() {
        "launched"
    }
}

def ss = new SecretService()

assert ss.@secret == "secret" // can access the private field directly
assert ss.launchOperation() == "launched" // can access the private method

Groovy++ 则在编译时限制这种访问,对Groovy++,上面例子"ss.@secret" 会导致 "Cannot access field test.SecretService.secret"; "ss.launchOperation()" 会导致 "Cannot access method SecretService.launchOperation()"。

5.还有一些小的差别

例10:Script binding 变量

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */
//@Typed
package test

foo = "foo"

assert foo == "foo"

上述例子对Groovy没有问题,变量foo是在script中绑定的。但在Groovy++ 中不支持,如果要在Groovy中使用这一特性,得用@Typed(TypePolicy.MIXED)标注方式。

例11:对map的属性风格访问

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */
//@Typed
package test

def map = [key1: "value1"]

assert map.key1 == "value1"

map.key1这种方式访问map,对Groovy没问题,但 Groovy++不支持,除非用MIXED模式。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读