클로저(Closure)는 outer scope(상위 함수의 영역)의 변수를 접근할 수 있는 함수를 말합니다. 코틀린은 클로저를 지원하며 그렇기 때문에 익명함수는 함수 밖에서 정의된 변수에 접근할 수 있습니다.
예로, 코틀린은 클로저를 지원하기 때문에 아래와 같은 코드를 사용할 수 있습니다.
fun add(x: Int): (Int) -> Int {
return fun(y: Int): Int {
return x + y
}
}
fun main(args: Array<String>) {
val func = add(10)
val result = func(20)
println(result)
}
위의 코드에서 add
함수는 익명함수를 리턴하는데요. 익명함수는 변수 x
에 접근할 수 없을 것 같습니다. 왜냐하면
x
는 전역변수도, 익명함수의 인자도 아니고 내부에서 정의하지 않았기 때문에 컴파일 에러가 발생해야 할 것 같습니다.
하지만 실행해보면 잘 동작합니다. 그 이유는 바로 코틀린이 클로저를 지원하기 때문입니다.
다시 말씀드리면, 함수 밖에 정의된 변수들을 사용할 수 있는 함수를 클로저라고 합니다. 코틀린은 클로저를 지원하며 그렇기 때문에 위 코드에서 익명함수는 문제 없이 함수 밖에서 정의된 변수에 접근할 수 있었습니다.
클로저(Closure)의 의미
Closure라는 말은 close over
에서 왔습니다.
StackOverflow의 설명을 참조하였습니다.
아래 코드에서 "The function named closure is said to “close over” the variable named x."라고 할 수 있습니다.
function add(x) {
return function closure(y) {
return x + y;
};
}
함수 closure는 변수 x를 쥐고있다(뒤덮다?)로 해석이 되는 것 같은데요. 그래서 클로저는 outer scope의 변수를 참조할 수 있는 함수를 말합니다.
클로저(Closure) 예제(1)
forEach
함수는 익명함수를 인자로 받습니다. 람다식으로 생성한 익명함수도 클로저 함수이며, outer scope의 변수에 접근할 수 있습니다.
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it
}
print(sum)
위의 코드에서 forEach
의 인자 익명함수는 밖에 정의된 sum
에 값을 저장하였습니다.
클로저(Closure) 예제(2)
안드로이드에서 자바로 아래처럼 리스너를 만들면 컴파일이 안됩니다.
왜냐하면 int x
가 final이 아니기 때문입니다. 자바의 익명 객체는 outer scope의 변할 수 있는 객체를 참조할 수 없기 때문입니다.
int x = 5;
view.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
System.out.println(x);
}
});
하지만 코틀린은 이런 코드가 가능합니다.
var x = 5
view.setOnClickListener {
println(x)
}
x가 5일 때 View가 클릭되면 5를 출력합니다. 하지만 x가 10으로 변경되고 View를 클릭하면 10을 출력합니다.
정리
함수 밖에 정의된 변수들에 접근할 수 있는 클로저 함수에 대해서 알아보았습니다. 클로저라는 컨셉은 매우 간단하지만, 복잡한 구조를 간단히 만들 수 있기 때문에 매우 유용합니다.
참고
Related Posts
- Kotlin - 배열에서 최소 값, 최대 값 찾기
- Kotlin - 2차원 배열 선언, 초기화 방법
- Kotlin - 배열 선언, 초기화 방법
- Kotlin - 리스트, 배열 길이 가져오기
- Kotlin - 리스트에서 최대, 최소 값 찾기
- Kotlin - for 반복문, 배열/리스트 순회
- Kotlin - Timer, 주기적으로 함수 실행
- Kotlin - sleep, 쓰레드 몇 초 지연
- Kotlin - Thread 생성 및 실행
- Kotlin에서 정규표현식 사용하기
- Kotlin - 문자열 길이 계산
- Kotlin - 문자열 비교 방법(equals, ==, compareTo)
- Kotlin - 2개의 배열 하나로 합치기
- Kotlin - 2개의 List 하나로 합치기
- Kotlin - 디렉토리의 모든 파일 리스트 출력
- Kotlin - 리스트 정렬 방법 (sort, sortBy, sortWith)
- Kotlin - 문자열 뒤집기 (Reverse String)
- Kotlin - 랜덤 숫자 생성 (Random, SecureRandom)
- Kotlin - Range, 숫자 범위 표현
- Kotlin - 음수를 양수로 변환, math.abs()
- Kotlin - List를 Set로 변환
- Kotlin - Set를 List로 변환
- Kotlin - 문자열에서 숫자(int)만 추출하는 방법
- Kotlin - Map을 List로 변환하는 방법
- Kotlin - File, Directory가 존재하는지 확인
- Kotlin - List를 Map으로 변환
- Kotlin - List의 중복 요소 제거
- Kotlin - List를 Array로 변환
- Kotlin - 엘비스 연산자 (Elvis Operation)
- Kotlin - Array를 List로 변환
- Kotlin - String을 Float으로 변환
- Kotlin - String을 Double으로 변환
- Kotlin - String을 Int로 변환
- Kotlin - String을 Long으로 변환
- Kotlin - String Null 또는 Empty 체크