什么是实际的Gpath和链接方法?

时间:2012-02-04 15:07:08

标签: groovy

我对这两行编码感到困惑:

this.class.methods.name

这叫做Gpath(我是对的吗?)。现在考虑这段代码:

count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }​.each { count ++ }
println count

该行:

a.findAll { it == 5 }​.each { count ++ }

被称为方法链接或Gpath?

从字面上看,我对这两个含义感到震惊。如果有人解释这两者之间的区别,那就太好了。

提前致谢。

2 个答案:

答案 0 :(得分:3)

我不确定我是否正确理解了这个问题。

在我看来,在两个示例中,您使用方法链接,只是因为您正在调用另一个方法返回的对象中的方法。但是,正如Arturo mentions,有些人混淆了方法链和fluent interfaces。如果你想链接方法,一个流畅的界面确实非常方便。

但是,在Groovy中,您可以使用任何对象中的with方法,而不是自己编写流畅的界面。例如,使用Arturo定义的相同PersonAddress类,您可以执行以下操作:

def person = new Person()
person.with {
    name = 'John'
    age = 25
    address = new Address('Boulevard St')
}
assert person.name == 'John' &&
       person.age == 25 &&
       person.address.name == 'Boulevard St'

现在,据我所知, GPath 只是一种访问对象属性的方法。例如,如果您有类:

class Foo {
    def bar
}

Groovy中的GPath机制允许您执行以下操作:

def foo = new Foo(bar: 42)
assert foo.bar == 42

而不是使用getter访问bar属性,例如foo.getBar()。没什么太花哨的。但是Groovy中的其他类也有一些GPath魔法,而且事情变得更有趣。例如,列表允许您以与访问普通属性相同的方式访问其元素中的属性:

def foos = (1..5).collect { new Foo(bar: it) } // Five Foos.
assert foos.bar == [1, 2, 3, 4, 5]

如您所见,访问具有该属性的对象列表上的bar属性将导致列表中包含该列表中每个对象的该属性的值。但是,如果您访问列表元素不具有的属性,例如foos.baz,它会抛出一个MissingPropertyException。

这正是发生在:

this.class.methods.name
但是,我认为这种行为对我来说有点太神奇(除非你正在解析XML,在这种情况下完全没问题)。请注意,如果methods方法返回的集合是一些具有name属性的奇怪集合,methods.name将导致该名称而不是集合中每个方法的名称。在这些情况下,我更喜欢使用(IMO)更明确的版本:

this.class.methods*.name

Wich会给你相同的结果,但它只是语法糖:

this.class.methods.collect { it.name }

...让表达的意图更加清晰(即“我想要methods中每个方法的名称”)。


最后,这是非常偏离主题的代码:

count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }​.each { count ++ }
println count

可以改写为:

def a = [1,2,3,4,5,5,51,2]
def count = a.count { it == 5 }
println count

:)

答案 1 :(得分:2)

我认为您的代码是方法链的一个示例

GPath是集成到Groovy中的路径表达式语言,允许在XML或POJO中导航。您可以在对象中执行嵌套属性访问。

Method chaining 是一种在面向对象的编程语言中调用多个方法调用的技术。每个方法都返回一个对象(可能是当前对象本身),允许在单个语句中将调用链接在一起。

我将使用TupleConstructor的示例来帮助创建对象。

import groovy.transform.TupleConstructor

@TupleConstructor
class Address {
    String name
}

@TupleConstructor
class Person {
    String name
    Integer age
    Address address
}

def person = new Person('John', 25, new Address('Boulevard St'))


好的,你是对的,这种访问称为GPath:

assert person.address.name == 'Boulevard St'

getter访问可以命名为方法链接:

assert person.getAddress().getName() == 'Boulevard St'


但如果我能做到这样的事情会发生什么:

person.setName('Louise')
      .setAge(40)
      .setAddress(new Address('Main St'))

我需要创建一个流畅的API,方法链接是方法,我们的想法是让方法返回this而不是void

@TupleConstructor
class Person {
    String name
    Integer age
    Address address

    def setName(name) {
        this.name = name
        return this
    }

    def setAge(age) {
        this.age = age
        return this
    }
}