2014年1月28日 星期二

[ In Action ] Working with closures - Declaring closures

Preface:
So far, we have used the simple abbreviated syntax of closures: After a method call, put your code in curly braces with parameters delimited from the closure body by an arrow. Let’s start by adding to your knowledge about the simple abbreviated syntax, and then we’ll look at two more ways to declare a closure: by using them in assignments and by referring to a method.

The simple declaration:
Listing 5.1 shows the simple closure syntax plus a new convenience feature. When there is only one parameter passed into the closure, its declaration is optional. The magic variable it can be used instead. See the two equivalent closure declarations in listing 5.1.
Listing 5.1 Simple abbreviated closure declaration
  1. log = ''  
  2. (1..10).each{ counter -> log += counter }  
  3. assert log == '12345678910'  
  4. log = ''  
  5. (1..10).each{ log += it }  
  6. assert log == '12345678910'  
Note that unlike counter , the magic variable it needs no declaration.

This syntax is an abbreviation because the closure object as declared by the curly braces is the last parameter of the method and would normally appear within the method’s parentheses. As you will see, it is equally valid to put it inside parentheses like any other parameter, although it is hardly ever used this way:
  1. log = ''  
  2. (1..10).each({ log += it })  
  3. assert log == '12345678910'  
This syntax is simple because it uses only one parameter, the implicit parameter it . Multiple parameters can be declared in sequence, delimited by commas. A default value can optionally be assigned to parameters, in case no value is passed from the method to the closure. We will show examples in section 5.4.

Using assignments for declaration:
A second way of declaring a closure is to directly assign it to a variable:
  1. def printer = { line -> println line }   
The closure is declared inside the curly braces and assigned to the printer variable.
TIP. Whenever you see the curly braces of a closure, think: new Closure(){} .

There is also a special kind of assignment, to the return value of a method:
  1. def Closure getPrinter() {  
  2.     return { line -> println line }  
  3. }  
Again, the curly braces denote the construction of a new closure object. This object is returned from the method call.
TIP.
Curly braces can denote the construction of a new closure object or a Groovy block. Blocks can be class, interface, static or object initializers, or method bodies; or can appear with the Groovy keywords if , else , synchronized , for , while , switch , try , catch , and finally . All other occurrences are closures.

As you see, closures are objects. They can be stored in variables, they can be passed around, and, as you probably guessed, you can call methods on them. Being objects, closures can also be returned from a method.

Referring to methods as closures:
The third way of declaring a closure is to reuse something that is already declared: a method. Methods have a body, optionally return values, can take parameters, and can be called. The similarities with closures are obvious, so Groovy lets you reuse the code you already have in methods, but as a closure. Referencing a method as a closure is performed using the reference .& operator. The reference is used to specify which instance should be used when the closure is called, just like a normal method call to reference.someMethod() . Figure 5.1 shows an assignment using a method closure, breaking the statement up into its constituent parts.


Below demonstrates method closures in action, showing two different instances being used to give two different closures.
- Listing 5.2 Simple method closures in action
  1. class MethodClosureSample {  
  2.     int limit  
  3.       
  4.     MethodClosureSample (int limit) {     
  5.         this.limit = limit                
  6.     }                                       
  7.       
  8.     boolean validate (String value) {       
  9.         return value.length() <= limit      
  10.     }                                       
  11. }  
  12.   
  13. // 1) Normal constructor calls  
  14. MethodClosureSample first = new MethodClosureSample (6)      
  15. MethodClosureSample second = new MethodClosureSample (5)     
  16.   
  17. // 2) Method closure assignment  
  18. Closure firstClosure = first.&validate  
  19.   
  20. def words = ['long string''medium''short''tiny']  
  21. assert 'medium' == words.find (firstClosure)        // 3) Calling the closure  
  22. assert 'short' == words.find (second.&validate)     // 4) Passing a method closure directly  
Method closures are limited to instance methods, but they do have another interesting feature—runtime overload resolution, also known as multimethods. You will find out more about multimethods in chapter 7, but listing 5.3 gives a taste.
- Listing 5.3 Multimethod closures—the same method name called with different parameters is used to call different implementations
  1. class MultiMethodSample {  
  2.       
  3.     int mysteryMethod (String value) {  
  4.         return value.length()  
  5.     }  
  6.       
  7.     int mysteryMethod (List list) {  
  8.         return list.size()  
  9.     }  
  10.       
  11.     int mysteryMethod (int x, int y) {  
  12.         return x+y  
  13.     }  
  14. }  
  15. MultiMethodSample instance = new MultiMethodSample()  
  16. // 1) Only a single closure is created  
  17. Closure multi = instance.&mysteryMethod         
  18.   
  19. // 2) Different implementations are called based on argument types          
  20. assert 10 == multi ('string arg')                
  21. assert 3 == multi (['list''of''values'])     
  22. assert 14 == multi (68)   
Comparing the available options:
Listing 5.4 shows all of these ways of creating and using closures: through simple declaration, assignment to variables, and method closures. In each case, we call theeach method on a simple map, providing a closure that doubles a single value. By the time we’ve finished, we’ve doubled each value three times.
- Listing 5.4 Full closure declaration examples
  1. map = ['a':1'b':2]                                
  2. map.each{ key, value -> map[key] = value * 2 }  // 1) Parameter sequence with commas   
  3. assert map == ['a':2'b':4]                        
  4.                                              
  5. // 2) Assign and then call a closure reference         
  6. doubler = {key, value -> map[key] = value * 2 }     
  7. map.each(doubler)                                   
  8. assert map == ['a':4'b':8]                        
  9.            
  10. // 3) A usual method declaration                                           
  11. def doubleMethod (entry){                
  12.     map[entry.key] = entry.value * 2     
  13. }           
  14.   
  15. // 4) Reference and call a method as a closure                               
  16. doubler = this.&doubleMethod      
  17. map.each(doubler)                 
  18. assert map == ['a':8'b':16]  
In order to fully understand how closures work and how to use them within your code, you need to find out how to invoke them. That is the topic of the next section.
- Listing 7.5 Declaring methods
  1. class TestClass {  
  2.     static void main(args) {  
  3.         def some = new TestClass()  
  4.         some.publicVoidMethod()  
  5.         assert 'hi' == some.publicUntypedMethod()  
  6.         assert 'ho' == some.publicTypedMethod()  
  7.         combinedMethod() // Call static method of current class  
  8.     }  
  9.     void publicVoidMethod(){}  
  10.     def publicUntypedMethod(){return 'hi'}  
  11.     String publicTypedMethod(){return 'ho'}  
  12.     protected static final void combinedMethod(){}  
  13. }  
The main method has some interesting twists. First, the public modifier can be omitted because it is the default. Second, args usually has to be of type String[] in order to make the main method the one to start the class execution. Thanks to Groovy’s method dispatch, it works anyway, although args is now implicitly of static typejava.lang.Object . Third, because return types are not used for the dispatch, we can further omit the void declaration.
NOTE.
The Java compiler fails on missing return statements when a return type is declared for the method. In Groovy, return statements are optional, and therefore it’s impossible for the compiler to detect “accidentally” missing returns.

This message was edited 25 times. Last update was at 17/01/2014 11:47:05

2014年1月26日 星期日

[ In Action ] Working with closures - The case for closures

Preface: 
Closures are important. Very important. They’re arguably one of the most useful features of Groovy—but at the same time they can be a strange concept until you fully understand them. In order to get the best out of Groovy, or to understand anyone else’s Groovy code, you’re going to have to be comfortable with them. Not just “met them once at a wedding” comfortable, but “invite them over for a barbecue on the weekend” comfortable. 

Let’s start with a simple definition of closures, and then we’ll expand on it with an example. closure is a piece of code wrapped up as an object. It acts like a method in that it can take parameters and it can return a value. It’s a normal object in that you can pass a reference to it around just as you can a reference to any other object. Don’t forget that the JVM has no idea you’re running Groovy code, so there’s nothing particularly odd that you could be doing with a closure object. It’s just an object. Groovy provides a very easy way of creating closure objects and enables some very smart behavior. 

If it helps you to think in terms of real-world analogies, consider an envelope with a piece of paper in it. For other objects, the paper might have the values of variables on it: “x=5, y=10” and so on. For a closure, the paper would have a list of instructions. You can give that envelope to someone, and that person might decide to follow the instructions on the piece of paper, or they might give the envelope to someone else. They might decide to follow the instructions lots of times, with a different context each time. For instance, the piece of paper might say, “Send a letter to the person you’re thinking of,” and the person might flip through the pages of their address book thinking of every person listed in it, following the instructions over and over again, once for each contact in that address book. 

The Groovy equivalent of that example would be something like this: 
  1. Closure envelope = { person -> new Letter(person).send() }  
  2. addressBook.each (envelope)  
That’s a fairly long-winded way of going about it, and not idiomatic Groovy, but it shows the distinction between the closure itself (in this case, the value of the envelopevariable) and its use (as a parameter to the each method). Part of what makes closures hard to understand when coming to them for the first time is that they’re usually used in an abbreviated form. Groovy makes them very concise because they’re so frequently used—but that brevity can be detrimental to the learning process. Just for the comparison, here’s the previous code written using the shorthand Groovy provides. When you see this shorthand, it’s often worth mentally separating it out into the longer form: 
  1. addressBook.each { new Letter(it).send() }  
It’s still a method call passing a closure as the single parameter, but that’s all hidden—passing a closure to a method is sufficiently common in Groovy that there are special rules for it. Similarly, if the closure needs to take only a single parameter to work on, Groovy provides a default name— it —so that you don’t need to declare it specifically. That’s how our example ends up so short when we use all the Groovy shortcuts. 

The case for closures 
We’ll look at two particular areas that benefit from closures: performing everyday tasks with collections, and using resources in a safe manner. In these two common situations, you need to be able to perform some logic that is the same for every case and execute arbitrary code to do the actual work. In the case of collections, that code is the body of the iterator; in the case of resource handling, it’s the use of the resource after it’s been acquired and before it’s been released. In general terms, such a mechanism uses a callback to execute the work. Closures are Groovy’s way of providing transparent callback targets as first-class citizens

Using iterators: 
A typical construction in Java code is traversing a collection with an iterator: 
  1. // Java  
  2. for (Iterator iter = collection.iterator(); iter.hasNext();){  
  3.     ItemType item = (ItemType) iter.next();  
  4.     // do something with item  
  5. }  
With a specific implementation of Collection , or an interface such as List , there may be options such as the following: 
  1. // Java  
  2. for (int i=0; i < list.size(); i++){  
  3.     ItemType item = (ItemType) list.get(i);  
  4.     // do something with item  
  5. }  
Java 5 improves the situation with two new features: generics and the enhanced for statement. Generics allow both to be written without casts; indeed, straight-forward iteration can be written in a form that is very similar to the Groovy for loop, using : instead of in : 
  1. // Java 5  
  2. for (ItemType item : list) {  
  3.       // do something with item  
  4. }  
Issue with the enhanced for statement brings us closer to closures, however. Clearly it’s useful to have a for loop that iterates through every item in a collection—otherwise Groovy wouldn’t have it, for starters. (Groovy’s for statement is somewhat broader in scope than Java 5’s—see chapter 6 for more details.) It’s useful, but it’s not everything we could wish for. There are common patterns for why we want to iterate through a collection, such as finding whether a particular condition is met by any element, finding all the elements met by a condition, or transforming each element into another, thereby creating a new collection

It would be madness to have a specialized syntax for all of those patterns. Making a language too smart in a non-extensible way ends up like a road through the jungle—it’s fine when you’re doing something anticipated by the designers, but as soon as you stray off the path, life is tough. So, without direct language support for all those patterns, what’s left? Each of the patterns relies on executing a particular piece of code again and again, once for each element of the collection. Java has no concept of “a particular piece of code” unless it’s buried in a method. That method can be part of an interface implementation, but at that point each piece of code needs its own (possibly anonymous) class, and life gets very messy. 

Groovy uses closures to specify the code to be executed each time and adds the extra methods ( each , find , findAll , collect , and so forthto the collection classes to make them readily available. Those methods aren’t magic, though—they’re simple Groovy, because closures allow the controlling logic (the iterationto be separated from the code to execute for every element. If you find yourself wanting a similar construct that isn’t already covered by Groovy, you can add it easily. 

Separating iteration logic from what to do on each iteration is not the only reason for introducing the closure concept. A second reason that may be even more important is the use of closures when handling resources. 

Handling resources: 
How many times have you seen code that opens a stream but calls close at the end of the method, overlooking the fact that the close statement may never be reached when an exception occurs while processing? So, it needs to be protected with a try-catch block. No—wait—that should be try-finally , or should it? And inside the finallyblock, close can throw another exception that needs to be handled. There are too many details to remember, and so resource handling is often implemented incorrectly. With Groovy’s closure support, you can put that logic in one place and use it like this: 
  1. new File('myfile.txt').eachLine { println it }  
The eachLine method of File now takes care of opening and closing the file input stream properly which prevent a resource leak of file handles. 

Streams are just the most obvious tip of the resource-handling iceberg. Database connections, native handles such as graphic resources, network connections—even your GUI is a resource that needs to be managed (that is, repainted correctly at the right time), and observers and event listeners need to be removed when the time comes, or you end up with a memory leak. 

Resource-handling code is often tested poorly. Projects that measure their test coverage typically struggle to fully cover this area. That is because duplicated, widespread resource handling is difficult to test and eats up precious development time. Testing centralized handlers is easy and requires only a single test. 

Let’s see what resource handling solutions Java provides and why they are not used often, and then we’ll show the corresponding Groovy solutions. 

A common Java approach: use inner classes 
In order to do centralized resource handling, you need to pass resource-using code to the handler. This should sound familiar by now—it’s essentially the same problem we encountered when considering collections: The handler needs to know how to call that code, and therefore it must implement some known interface. In Java, this is frequently implemented by an inner class for two reasons: First, it allows the resource-using code to be close to the calling code (which is often useful for readability); and second, it allows the resource-using code to interact with the context of the calling code, using local variables, calling methods on the relevant object, and so on. 

Anonymous inner classes are almost solely used for this kind of pattern—if Java had closures, it’s possible that anonymous inner classes might never have been invented. The rules and restrictions that come with them (and with plain inner classes) make it obvious what a wart the whole “feature” really is on the skin of what is otherwise an elegant and simple language. As soon as you have to start typing code like MyClass.this.doSomething , you know something is wrong—and that’s aside from the amount of distracting clutter required around your code just to create it in the first place. The interaction with the context of the calling code is limited, with rules such as local variables having to be final in order to be used making life awkward

In some ways, it’s the right approach, but it looks ugly, especially when used often. Java’s limitations get in the way too much to make it an elegant solution. The following example uses a Resource that it gets from a ResourceHandler , which is responsible for its proper construction and destruction. 
  1. // Java  
  2. interface ResourceUser {  
  3.   void use(Resource resource)  
  4. }  
  5. resourceHandler.handle(new ResourceUser(){  
  6.     public void use (Resource resource) {  
  7.         resource.doSomething()  
  8.     }  
  9. });  
The Groovy equivalent of this code reveals all necessary information without any waste: 
  1. resourceHandler.handle { resource -> resource.doSomething() }  
Groovy’s scoping is also significantly more flexible and powerful, while removing the “code mess” that inner classes introduce. 

An alternative Java approach: the Template Method pattern 
Another strategy to centralize resource handling in Java is to do it in a superclass and let the resource-using code live in a subclass. This is the typical implementation of the Template Method [GOF] pattern

The downside here is that you either end up with a proliferation of subclasses or use (maybe anonymousinner subclasses, which brings us back to the drawbacks discussed earlier. It also introduces penalties in terms of code clarity and freedom of implementation, both of which tend to suffer when inheritance is involved. This leads us to take a close look at the dangers of abstraction proliferation

If there were only one interface that could be used for the purpose of passing logic around, like our imaginary ResourceUser interface from the previous example, then things would not be too bad. But in Java there is no such beast—no single ResourceUser interface that serves all purposes. The signature of the callback method useneeds to adapt to the purpose: the number and type of parameters, the number and type of declared exceptions, and the return type. 

Therefore a variety of interfaces has evolved over time: Runnables, Observers, Listeners, Visitors, Comparators, Strategies, Commands, Controllers, and so on. This makes their use more complicated, because with every new interface, there also is a new abstraction or concept that needs to be understood. In comparison, Groovy closures can handle any method signature, and the behavior of the controlling logic may even change depending on the signature of the closure provided to it, as you’ll see later. These two examples of pain-points in Java that can be addressed with closures are just that—examples. If they were the only problems made easier by closures, closures would still be worth having, but reality is much richer. It turns out that closures enable many patterns of programming that would be unthinkable without them. 

Supplement: 
Document > User Guide > Closures 
Working with closures - Declaring closures

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...