시작하기에 앞서...
아래 예제들을 실행해보기 전에 우선 다음을 참고하세요:
- Groovy를 설치하고
- 임베딩하고
- 실행해보세요.
- 명령행 을 통해 쉘 스크립트 모드로 실행하거나
- 보통의 자바 프로그램처럼 컴파일해서 실행하거나
- Bean Scripting Framework 을 이용하여 Groovy를 자바 코드 안에 포함시킬 수도 있습니다.
첫번째 Groovy
| Code Block |
|---|
|
//hello.groovy
println "hello, world"
for (arg in this.args ) {
println "Argument:" + arg;
}
// 이건 주석이고
/* 이건 블럭 단위 주석 입니다. 아래처럼 할 수도 있습니다:
this.args.each{ arg -> println "hello, ${arg}"}
*/
|
명령행에서 위 코드를 실행하려면 다음과 같이 하세요:
| Code Block |
|---|
|
groovy hello.groovy MyName yourName HisName
|
개괄
Groovy 클래스는 결국 자바 바이트 코드로 컴파일 되기 때문에 Groovy 클래스와 자바 클래스 사이에는 일대일 대응이 성립합니다. 사실 모든 Groovy 클래스는 보통의 자바 코드 안에서 그대로 쓰일 수 있습니다. 왜냐하면 Groovy 클래스도 자바 클래스이기 때문입니다.
Groovy의 장점을 파악할 수 있는 가장 쉬운 방법은 콜랙션을 다루는 코드를 실험해보는 것입니다. Groovy에서는 List(java.util.List)와 Map(java.util.Map)이 모두 문법상 first class 객체입니다. 따라서 객체의 List를 생성하려면 아래와 같이 하면 됩니다:
| Code Block |
|---|
|
def list = [1, 2, 'hello', new java.util.Date()]
assert list.size() == 4
assert list.get(2) == 'hello'
assert list[2] == 'hello'
|
모든 것이 객체라는 점을 주목하세요(숫자의 경우 자동 박싱이 적용됩니다). Map을 만들려면 아래와 같이 합니다:
| Code Block |
|---|
|
def map = ['name':'James', 'location':'London']
assert map.size() == 2
assert map.get('name') == 'James'
assert map['name'] == 'James'
|
콜랙션을 순회(iterate)하는 것도 쉽습니다:
| Code Block |
|---|
|
def list = [1, 2, 3]
for (i in list) { println i }
|
일단 콜랙션을 만들었으면 Groovy의 새로운 콜랙션 지원 메서드(hepler methods)나 클로저를 사용해볼 수 있습니다.
클로저(closure) 사용하기
클로저는 자바의 내부 클래스(inner class)와 비슷합니다. 단 클로저는 임의의 인자를 갖는 실행 가능한 단일 메서드라는 점이 다릅니다. 클로저는 원하는 만큼의 인자를 가질 수 있습니다:
| Code Block |
|---|
|
def closure = { param -> println("hello ${param}") }
closure.call("world!")
closure = { greeting, name -> println(greeting + name) }
closure.call("hello ", "world!")
|
-> 표시 이전에 아무런 인자도 지정하지 않으면 'it'이라는 이름의 기본 인자가 사용됩니다. 아래 예제를 참고하세요:
| Code Block |
|---|
|
def closure = { println "hello " + it }
closure.call("world!")
|
클로저를 이용하면 아래와 같이 콜랙션(Array, Map, String, File, SQL connection)을 더 깔끔하게 쓸 수 있습니다:
| Code Block |
|---|
|
[1, 2, 3].each ({ item -> print "${item}-" })
["k1":"v1", "k2":"v2"].each {key, value -> println key + "=" + value}
|
참고: 메서드의 마지막 인자가 클로저인 경우 클로저의 정의는 괄호 밖으로 빠져나갈 수 있습니다. 아래 코드들을 살펴보세요:
| Code Block |
|---|
|
def fun(int i, Closure c) {
c.call(i)
}
// 클로저를 괄호 밖으로 빼기
[1, 2, 3].each() ({ item -> print "${item}-" })
fun(123) { i -> println i }
// 괄호 생략
[1, 2, 3].each ({ item -> print "${item}-" })
// 일반적인 용법
[1, 2, 3].each(({ item -> print "${item}-" }))
def closure = { i -> println i}
//[1, 2, 3].each() closure // 에러. 클로저를 이미 정의했음
|
다음은 콜랙션과 String에서 쓸 수 있는 지원 메서드들입니다.
each
클로저를 이용하여 순회:
| Code Block |
|---|
|
[1, 2, 3].each { item -> print "${item}-" }
|
collect
콜랙션의 각 아이템에 대해 클로저를 호출하고 그 결과를 수집:
| Code Block |
|---|
|
def value = [1, 2, 3].collect { it * 2 }
assert value == [2, 4, 6]
|
find
클로저로 주어진 조건(predicate)과 일치하는 첫번째 아이템을 반환:
| Code Block |
|---|
|
def value = [1, 2, 3].find { it > 1 }
assert value == 2
|
findAll
클로저로 주어진 조건과 일치하는 모든 아이템을 반환:
| Code Block |
|---|
|
def value = [1, 2, 3].findAll { it > 1 }
assert value == [2, 3]
|
inject
첫 반복(iteration)에서 사용할 값을 인자로 넘기고 그 반복에서 처리한 결과를 다음 반복으로 넘기는 것을 되풀이합니다. 셈을 할 때에 특히 유용합니다:
| Code Block |
|---|
|
def value = [1, 2, 3].inject('counting: ') { str, item -> str + item }
assert value == "counting: 123"
value = [1, 2, 3].inject(0) { count, item -> count + item }
assert value == 6
|
이에 더하여 콜랙션에 대한 부울린 로직을 수행하는 두 개의 메서드도 제공됩니다.
every
콜랙션의 모든 요소가 클로저에 의해 제공되는 술어(predicate)를 만족하면 참을 반환합니다:
| Code Block |
|---|
|
def value = [1, 2, 3].every { it < 5 }
assert value
value = [1, 2, 3].every { item -> item < 3 }
assert ! value
|
any
콜랙션의 요소 중 어떤 한 가지라도 클로저에 의해 제공되는 술어를 만족하면 참을 반환합니다:
| Code Block |
|---|
|
def value = [1, 2, 3].any { it > 2 }
assert value
value = [1, 2, 3].any { item -> item > 3 }
assert value == false
|
기타 지원 메서드에는 다음과 같은 것들이 있습니다.
max / min
Comparable을 구현한 객체의 콜랙션에 대하여 최대값(max) / 최소값(min)을 반환합니다:
| Code Block |
|---|
|
value = [9, 4, 2, 10, 5].max()
assert value == 10
value = [9, 4, 2, 10, 5].min()
assert value == 2
value = ['x', 'y', 'a', 'z'].min()
assert value == 'a'
|
join
콜랙션의 모든 값을 연결하여 하나의 문자열로 만들어줍니다:
| Code Block |
|---|
|
def value = [1, 2, 3].join('-')
assert value == '1-2-3'
|