Ant's
Ant's

Reputation: 13811

What Are Actually Gpath And Chaining methods?

I got confused with this two lines of coding :

this.class.methods.name

This is called Gpath (Am I right?). Now consider this code :

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

The line:

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

is called as a method chaining or Gpath?

Literally, I got struck with these two meanings. It will be nice if some one explains the difference between these two.

Thanks in advance.

Upvotes: 0

Views: 845

Answers (2)

epidemian
epidemian

Reputation: 19229

I'm not sure if I understand the question correctly.

As I see it, in both examples you are using method chaining, simply because you are calling a method in the object that is returned by another method. But, as Arturo mentions, some people confuse method chaining and fluent interfaces. A fluent interface is indeed quite handy if you want to chain methods.

In Groovy, however, you may, instead of coding a fluent interface yourself, use the with method in any object. For example, using the same Person and Address classes that Arturo defined, you can do:

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'

Now, GPath, as I understand, is just a way of accessing the properties of an object. For example, if you have the class:

class Foo {
    def bar
}

The GPath mechanism in Groovy lets you do things like:

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

Instead of accessing the bar property with its getter, like foo.getBar(). Nothing too fancy. But other classes in Groovy also have some GPath magic and there is where things get more interesting. For example, lists let you access properties in their elements the same way you'd access normal properties:

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

As you can see, accessing the bar property on a list of objects that have that property will result in a list with the values of that property for each object in the list. But if you access a property that the elements of the list don't have, e.g. foos.baz, it will throw a MissingPropertyException.

This is exactly what is happening in:

this.class.methods.name

I, however, consider this behavior to be a little too magic for my taste (unless you are parsing XML, in which case is totally fine). Notice that if the collection returned by the methods method would be some weird collection that had a name property, methods.name would result in that name instead of the names of each method in the collection. In these cases I prefer to use the (IMO) more explicit version:

this.class.methods*.name

Wich will give you the same result, but it's just syntax sugar for:

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

... and let's the intention of the expression to be more clear (i.e. "I want the names of each method in methods").


Finally, and this is quite off-topic, the code:

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

can be rewritten as:

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

:)

Upvotes: 3

Arturo Herrero
Arturo Herrero

Reputation: 13122

I think that your code is an example of method chaining.

GPath is a path expression language integrated into Groovy which allows to navigate in XML or POJOs. You can perform nested property access in objects.

Method chaining is a technique for invoking multiple method calls in object-oriented programming languages. Each method returns an object (possibly the current object itself), allowing the calls to be chained together in a single statement.

I'm going to use an example with TupleConstructor to assist in the creation of the object.

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'))


Ok, you are right, this access is called GPath:

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

A getter access could be named method chaining:

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


But what happens if I can do something like this:

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

I need to create a fluent API, an method chaining is the way, the idea is to let methods return this rather than 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
    }
}

Upvotes: 2

Related Questions