Tuesday, September 27, 2011

Groovy differences from Java (2/2 part)

Here we will continue to describe differences between Groovy and Java. In this part we will describe more important concepts that separates Groovy from Java: closures and Groovy's dynamic nature.

Closures

Closures are something you will come across if you ever code in any functional language (Scheme, LISP and even JavaScript). Because in functional language everything is function, you pass these functions to another functions as arguments. Also you can give these function a name which will provide means for using name to refer to this function. When you have defined name you can also pass it to another function.

Why would you want to to this you may ask? Well, did you ever use template method design pattern. This design pattern shows you how you can defer implementation steps of some interface to subclasses and you can dynamically use whatever implementation you think is suited best at that moment. You are "injecting" some code to another code. This is what closures do. They "capture" some code and then you can reuse this code at other places. I know this is little bit confusing right now and my half-explanation is not helping at all. So here is how Groovy does it:

You are probably familiar with sort() method in Java. So here is example of code for sorting array in Java and in Groovy:

// We will define some list.
List cars = ["Skoda", "Honda", "Toyota", "Audi"]
// This is how Groovy sort this list.
// Bit behind sort function in within curly
// braces is closure. What it basically do is
// inserting some code (in this example 
// a.compareTo(b)) to sort function. That
// is what closures do. They encapsulate code.
// a and b are arguments to closure, bit behind
// -> is closure body.
cars.sort {String a, String b -> a.compareTo(b) }

println cars
// [Audi, Honda, Skoda, Toyota]

// In Java you have you must implement Comparator
// interface and override compare method. 
// We do this mainly through anonymous classes in
// Java. Should be familiar.
Collections.sort(cars, new Comparator() {
    public int compare(String a, String b) {
        return a.compareTo(b)
    }    
});

println cars
// [Audi, Honda, Skoda, Toyota]

// Another most common use of closure in
// Groovy is for .each method which will 
// loop through all elements in lists,maps,...
// This closure does not use argument, it 
// uses special variable "it" which represent
// single value from this list.
int sum = 0
[2, 3, 4].each { sum += it }
println sum
// 9

In Groovy you can also assign closure to variable and then pass them around (like function in functional language).
Closure comparator = {Integer a, Integer b ->
    a.compareTo(b)
}
// Passing a closure to method looks like
// normal method call.
[7, 1, 6, 7].sort(comparator)
// [1, 6, 7, 7]

Closures are effectively anonymous functions, but more powerful.

Dynamic programming

In Java all variables, properties, method arguments and method returns must have declared types. If you want to do some real dynamic things you can do it through reflections which is OK, but it is not really elegant way of doing things.

Groovy address this issue and brings dynamic behavior to Java world. But what is all this dynamic stuff anyway?

Imagine that you have a Person class with some properties (firstName, lastName for example). You can easily sort a list of Persons object like so:
// Using usual way of sorting stuff in Java
// by implementing Comparator...
public void sortPeopleByGivenName(List personList) {
    Collections.sort(personList, new Comparator() {
        public int compare(Person p1, Person p2) { 
            return p1.getFirstName().compareTo(p2.getFirstName());
        }
    } ) ;
}

But what if you don't know which property for sorting you will use until run time. You can do some magic with reflection here, but that is always bad idea because it looks odd, also you can do some "if-stuff", but what if you have 20 properties in your domain class...

Here is where you can use Groovy's dynamism and simply define property as String that will be resolved at runtime to some concrete property. This is called dynamic dispatch and it basically mean that groovy will "find" appropriate property at runtime (similar like dynamic binding is looking for appropriate method at runtime).
For example:
// Accessing property by "string".
// This is only possible in dynamic languages
// languages because properties and methods are resolved
// at run time (Duck Typing)
def sortPeople(people, property) {
    people.sort { p1, p2 
     -> p1."${property}" <=> p2."${property}" }
}
Groovy uses def keyword to specify untyped methods and variables. It is important to note that Groovy support declared types (because of Java heritage) and that is one of the main strengths of Groovy (that and Java background off course).

No comments:

Post a Comment