클로저는 내부함수가 외부함수의 context에 접근 할 수 있는 것을 가리킨다.
내부함수에서 외부함수의 데이터를 사용할 경우 외부함수의 코드블럭이 끝나도 내부함수에서 참조한 변수가 계속 살아있게된다. 이 뜻을 의미하려면 다음 코드예시를 보자.
fun main() {
fun outer(): () -> Int{
var x = 10
var innerFunc = fun():Int{
return println(++x)
}
return innerFunc
}
val func1 = outer()
func1() // 결과: 11
func1() // 무슨값이 나올지 한번 맞춰보세요!
}
정답은 외부함수 x 값이 살아있어 12가 나오게 된다.
이처럼 기본적인 개념은 어렵지 않다. 하지만 실제로는 어떻게 사용할까?
fun updateCommentCount(commentCount: CommentCount) {
update(commentCount.postId) {
it.commentCount = commentCount.commentCount
}
}
private fun update(id: Long, action: (Content) -> Unit) {
for ((i, content) in snapshot().withIndex()) {
content?.let {
if (it.id == id) {
action(it)
this@CommunityAdapter.notifyItemChanged(i)
return
}
}
}
}
위의 예시 함수를 보자.
update라는 함수가 정의되어있다.
id를 파라미터로 받고있는것을 알 수 있다.
그리고 뒤에 action을 실행시키는데 Content를 받아 Unit을 반환한다.
익숙한 for문을 돌고 withIndex를 이용하여 index와 content를 반환해준다.
content : Content 이기 때문에 content.let을 통해서 action에 넣을 Content Type을 준비한다.
content.id(==it.id) 가 파라미터로 받은 id와 동일한지 비교하고 맞다면
action(it)을 실행시킨다. 이때의 it은 파라미터부분에 정의한 Content Type 이다.
그 위의 updateCommentCount메서드를 보자.
원하는 파라미터를 받고 update 메서드를 호출하면서 id를 파라미터로 넣어준다.
이때 람다식에 나타나는 it은 action(Content)의 Content임을 알 수 있다.
그리고 람다식을 실행 시킬 수 있다.