그루비 클로저는 이름없는 메서드에 대한 포인터에 해당하며 함수를 함수 포인터에 저장하는것에 불과하다.
클로저 정의는 중괄호 { } 를 이용해서 하며 호출시는
<클로저명>.call() 또는 일반 메서드 처럼 <클로저명>( ) 으로 실행할 수 있다.
Groovy 에서는 아주 많은 부분에서 클로저를 사용하기 때문에 반드시 알고 활용할 수 있어야 한다.
Basic
def c = {}
println c.class.name
|
Test$_run_closure1
|
def exMap = [:]
def exClosure = {
println "Hello"
}
exMap.closureProp = exClosure
exMap.closureProp()
|
Hello
|
기본적으로 함수와 비슷하게 사용되지만 Argument 를 넣고자 하면 아래와 같이 해야 한다.
def sayHello = {
println "Hello"
}
def sayHelloWithArg = { name ->
println "Hello ${name}"
}
sayHello()
sayHelloWithArg('Dkim')
//Closure 를 인자로 받는 함수 제작
def timesTen(num,closure) {
closure(num*10)
}
//Closure 를 함수에 전달, it 을 사용하면 편리함, () 생략 가능
timesTen(10,{num-> println num})
timesTen(10,{println it})
timesTen 10,{println it}
|
Hello
Hello Dkim
100
100
100
|
Closure Parameter
파라미터 넣는 부분은 파라미터가 하나인 경우는 it 을 활용하고
아니면 -> 오퍼레이터로 여러 인자를 넣을 수 있다.
def fooWithIt = {
println it
}
fooWithIt ('foo1')
def fooWithParam = { name ->
println "${name}"
}
fooWithParam('foo2')
def fodWithMultiParam = { first, last ->
println "Hello ${first} ${last}"
}
fodWithMultiParam ("Daeung","Kim")
|
foo1
foo2
Hello Daeung Kim
|
Collections Method
Collection 데이터 타입의 메서드에는 Closer 를 인자로 받는 많은 메서드가 있다.
예를 들어 List 의 경우 each, eachWithIndex, findAll, .. 등의 메소드가 있다.
def nums =[1,2,3,4,5]
nums.each {println it}
nums.eachWithIndex{ int num, int index ->
println "${index} : ${num}"
}
def days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
List weekend = days.findAll {
it.startsWith('S')
}
println weekend
def numsTimesTen = nums.collect {num -> num * 10}
println numsTimesTen
|
1
2
3
4
5
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
[Sun, Sat]
[10, 20, 30, 40, 50]
|
Curry Methods
Curry 메서드는 클로저 를 랩핑하는 메서드로 클로저 메서드에 인자값을 특정하는 경우 유용하다.
말이 어려운데 사실 Default 값을 넣어놓은 클로저 메서드 정도로 이해하면 되겠다.
def log = { String type, Date createOn, String msg ->
println "$createOn [$type] - $msg"
}
log("Debug", new Date(), "First Msg")
def debugLog = log.curry("Debug")
debugLog(new Date(),"Curry First Msg")
debugLog(new Date(),"Curry Second Msg")
def specifiedPersonLog = log.rcurry("Im The Person")
specifiedPersonLog("ERROR", new Date())
|
Mon Oct 14 15:53:04 KST 2019 [Debug] - First Msg
Mon Oct 14 15:53:05 KST 2019 [Debug] - Curry First Msg
Mon Oct 14 15:53:05 KST 2019 [Debug] - Curry Second Msg
Mon Oct 14 15:55:18 KST 2019 [ERROR] - Im The Person
|
Closure Scope & Delegate
closer 내부에는 this 와 owner 와 delegate 라는 속성이 들어 있는데 위와 같이 정의된다.
this 는 클로저가 정의된 클래스를 가리키며 owner 는 클로저가 정의된 오브젝트를 가리키지만
delegate 는 자신을 call 한 third party 오브젝트를 가리킨다.
보통은 owner 와 delegate 는 일치하지만 owner 객체에서 자신을 call 할 수 있는 메서드가 없다면
외부에서 자신을 call 할 수 있는 메서드를 찾아 사용해버린다.
class ScopeDemo {
def outerClosure = {
println this.class.name
println owner.class.name
println delegate.class.name
def nestedClosure = {
println this.class.name // 클로저가 정의된 클래스
println owner.class.name // 클로저가 정의된 오브젝트
println delegate.class.name // Delegate 는 기본적으로 Closer 를 호출한 Object
}
nestedClosure()
}
}
def demo = new ScopeDemo()
demo.outerClosure()
|
ScopeDemo
ScopeDemo
ScopeDemo
ScopeDemo
ScopeDemo$_closure1
ScopeDemo$_closure1
|
그래서 다음과 같이 StringBuffer 객체가 Delegate 객체로 지정되어 writer 클로저가 동작하고
결과가 StringBuffer 객체에 저장되게 된다.
def writer = {
append 'Dan'
append " Lives In KangNam"
}
def sb = new StringBuffer()
writer.delegate = sb
writer()
println sb
|
Dan Lives In KangNam
|
'Script > Groovy' 카테고리의 다른 글
12. Exception (0) | 2020.01.21 |
---|---|
11. Conditional Statement (0) | 2020.01.21 |
09. Collection (0) | 2020.01.21 |
08. RegExp (0) | 2020.01.21 |
07. String (0) | 2020.01.21 |