Groovy天哪:使用Call运算符

Groovy Goodness: Using The Call Operator

在Groovy中,我们可以将名为call的方法添加到类中,然后在不使用名称call的情况下调用该方法。 我们只需要在对象实例上键入括号和可选参数即可。 Groovy将此称为调用运算符:()。 例如,这在用Groovy编写的DSL中特别有用。 我们可以向我们的类添加多个call方法,每个方法具有不同的参数。 根据参数在运行时调用正确的方法。

在下面的示例中,我们有一个带有三个call方法实现的User类。 接下来,我们看到如何调用call方法,但不键入方法名称而仅使用括号和参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import groovy.transform.ToString

@ToString(includeNames = true)
class User {

    String name
    String alias
    String email
    String website

    // Set name.
    def call(final String name) {
        this.name = name
        this
    }

    // Use properties from data to assign
    // values to properties.
    def call(final Map data) {
        this.name = data.name ?: name
        this.alias = data.alias ?: alias
        this.email = data.email ?: email
        this.website = data.website ?: website
        this
    }

    // Run closure with this object as argument.
    def call(final Closure runCode) {
        runCode(this)
    }

}


def mrhaki =
    new User(
        name: 'Hubert Klein Ikkink',
        alias: 'mrhaki',
        email: '[email protected]',
        website: 'https://www.mrhaki.com')

// Invoke the call operator with a String.
// We don't have to explicitly use the
// call method, but can leave out the method name.
// The following statement is the same:
// mrhaki.call('Hubert A. Klein Ikkink')
mrhaki('Hubert A. Klein Ikkink')

// Of course parentheses are optional in Groovy.
// This time we invoke the call method
// that takes a Map arguemnt.
mrhaki email: '[email protected]'

assert mrhaki.name == 'Hubert A. Klein Ikkink'
assert mrhaki.alias == 'mrhaki'
assert mrhaki.email == '[email protected]'
assert mrhaki.website == 'https://www.mrhaki.com'


// We can pass a Closure to the call method where
// the current instance is an argument for the closure.
// By using the call operator we have a very dense syntax.
mrhaki { println it.alias }  // Output: mrhaki

// Example to transform the User properties to JSON.
def json =  mrhaki {
    new groovy.json.JsonBuilder([vcard: [name: it.name, contact: it.email, online: it.website]]).toString()
}

assert json == '{"vcard":{"name":"Hubert A. Klein Ikkink","contact":"[email protected]","online":"https://www.mrhaki.com"}}'

用Groovy 2.4.8编写。