
2008.4.29 translation & editing by gilbird
원문: http://groovy.codehaus.org/Closures
gilbird: 위키피디아에서 클로져(Closure)란 함수를 영역안에 묶어 버리는 추상적인 묶음이라고 표현한다. 그루비에서 클로져를 사용하는 방법을 알아보기로 하자.
클로져(Closure)란 무엇인가?
그루비 클로져는 코드 블록 혹은 메서드 포인터와 같다. 클로져는 정의 후 나중에 실행할 코드 조각을 말한다.
간단한 예제
def clos = { println "hello!" }
println "Executing the closure:"
clos() // "hello!"를 출력한다.
위의 예에서 "hello!"는 클로져를 정의할때가 아니라 호출할때 출력된다는 점에 주목하기 보란다.
클로져는 정의한 영역의 변수에 묶일 수 있다.
def localMethod() {
def localVariable = new java.util.Date()
return { println localVariable }
}
def clos = localMethod()
println "Executing the closure:"
clos() //"localVariable"을 정의했을 때 날짜를 출력한다.
파라메터 (Parameters)
클로져 파라메터는 아래와 같이 -> 토큰 앞에 나열한다.
def clos = { a, b -> print a+b }
clos( 5, 7 ) //"12"를 출력한다.
-> 토큰은 클로져 정의에 파라메터가 하나 뿐이면 생략 가능한다. (gilbird: 아래 It 설명을 보기 바란다.)
명시적 변수(Implicit variables)
클로져 안에서 여러 변수가 특별한 의미로 쓰인다.
It
인자 하나만을 받아들이는 클로져가 있다면 다음과 같이 클로져 정의에서 파라메터를 뺄 수 있다.
def clos = { print it }
clos( "hi there" ) // "hi there"가 출력된다.
this, owner, delegate
this: 자바에서 this는 클로져를 정의한 클래스를 지칭한다.
owner: 둘러싼 객체 (this나 둘러싼 클로져)
delegate: 기본적으로 owner와 동일하지만 builder나 ExpandoMetaClass에서와 같이 변경가능함
예:
class Class1 {
def closure = {
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
}
def clos = new Class1().closure
clos.delegate = this
clos()
/* 출력:
Class1
Script1
Class1$_closure1 */
클로져와 메서드 인자
메서드에서 클로져를 마지막 인자로 받는다면 아래와 같이 클로져를 인라인으로 정의할 수 있다.
def list = ['a','b','c','d']
def newList = []
list.collect( newList ) {
it.toUpperCase()
}
println newList // ["A", "B", "C", "D"]
위 예에서 collect 메서드는 List와 클로져 인자를 받아들인다. 위 코드는 아래과 같이 표현할 수도 있다.
def list = ['a','b','c','d']
def newList = []
def clos = { it.toUpperCase() }
list.collect( newList, clos )
assert newList == ["A", "B", "C", "D"]
더 많은 정보
그루비에서는 java.lang.Object를 상속하여 여러 메서드가 클로져와 인자를 받아들이도록 했다. 클로져의 실제적인 사용법에 대해서는 Object를 확장하는 GDK를 참고하기 바란다.
- 클로져 - 공식적인 정의
- 클로져 - 비공식적 가이드