스코프 함수

Suyong Lee·2021년 9월 13일
0

Android

목록 보기
21/22
post-thumbnail

스코프 함수는 코드를 축약해서 표현할 수 있도록 도와주는 함수이며 영역 함수라고도 한다.

함수지만, run 이나 let 처럼 괄호 없이 키워드처럼 간편하게 사용할 수 있다는 장점이 있다.

lateinit과 함께 Safe Call 의 남용을 막아주는 역할도 하므로 자주 쓰는 요소다.

스코프 함수에는 run, let, apply, also, with 가 있다.

run 과 let

run과 let은 자신의 함수 스코프(코드 블럭) 안에서 호출한 대상을 this와 it으로 대체해서 사용할 수 있다.

run은 클래스 내부 함수를 사용하는 것과 동일한 효과이기 때문에 this는 생략 가능하다.

var list = mutableListOf("Scope", "Function")
list.run {
	val listSize = size // this를 생략하고 도트 연산자(.) 없이 프로퍼티를 바로 사용할 수 있다.
    println("리스트의 길이 run = $listSize")
}

let은 함수 영역 안에서 호출한 대상을 it으로 사용할 수 있다.

it은 생략 불가능하다.

var list = mutableListOf("Scope", "Function")
list.let {
	val listSize = it.size // 모든 속성과 함수를 it.멤버로 사용할 수 있다.
    println("리스트의 길이 let = $listSize")
}

this와 it으로 구분하기

this로 사용된느 스코프 함수에는 apply, with, 앞에서 알아본 run이 있다.

this 키워드 개념에 대해 기억할 것은 함수 안에서 자기 자신의 메서드나 프로퍼티를 this를 생략하고 직접 호출한다는 점이다.

(this를 생략하면 컴퓨터는 호출하려는 이 프로퍼티(혹은 메서드)는 어디서 온거야? 라고 에러를 발생시켜야 정상이지만 스코프 함수 내에서는 그렇지 않게 설계되었다는 뜻이다.

var list = mutableListOf("Scope", "Function")
list.apply {
	val listSize = size // this.size 가 아니라 size
    println("리스트의 길이 apply = $listSize")
}

with(list) {
	val listSize = size
    println("리스트의 길이 with = $listSize")
}

호출하는 대상이 null일 경우
with는 스코프 함수이긴 하지만 앞의 2개와는 다르게 확장 함수가 아니기 때문에 일반 함수처럼 사용된다. 따라서 null일 경우에는 with보다는 apply나 run을 사용하는 것이 효율적이다.

target?.apply{ /* 코드 */ }

it으로 사용되는 스코프 함수 : let , also

var list = mutableListOf("Scope", "Function")
list.let { target -> // it을 target 등과 같이 다른 이름으로 변경가능
	val listSize = target.size // target으로 변경했기 때문에 멤버 접근은 target 속성이다.
    println("리스트의 길이 let = $listSize")
}

list.also {
	val listSize = it.size
    println("리스트의 길이 also = $listSize")
}

호출 대상인 this 자체를 반환하는 스코프 함수 : apply, also

apply를 사용하면 스코프 함수 안에서 코드가 모두 완료된 후 자기 자신을 되돌려준다.

아래 코드를 보면 apply 스코프의 마지막 줄에서 count()를 호출했지만 마지막 코드와 상관없이 그냥 MutableList 자신을 돌려주기 때문에 Scope, Function에 Apply가 추가된 값이 출력된다.

also도 동일하게 동작한다.

var list = mutableListOf("Scope", "Function")

val afterApply = list.apply {
	add("Apply") // this는 생략 가능
    count() // 이 코드와 상관없이 list 자기 자신만 돌려줌
}
println("반환값 apply = $afterApply")

val afterAlso = list.also{
	it.add("Also") // it은 생략 불가
    it.count() // 이 코드와 상관없이 list 자기 자신만 돌려줌
}
println("반환값 also = $afterAlso")

반환값 apply = [Scope, Function, Apply]
반환값 also = [Scope, Function, Apply, Also] // list에 Apply가 add된 상태에서 Also를 add 했기 때문에 이런 반환값

마지막 실행 코드를 반환하는 스코프 함수: let, run, with

위 3가지 함수는 자기 자신이 아닌 스코프의 마지막 코드를 반환한다.

count() 함수 결과가 반환되어 리스트의 개수가 출력된다는 뜻이다.

var list = mutableListOf("Scope", "Function")

val lastCount = list.let {
	it.add("Run")
    it.count()
}
println("반환값 let = $lastCount")

val lastItem = list.run {
	add("Run")
    get(size-1)
}
println("반환값 run = $lastItem")

val lastItemWith = with(list) {
	add("With")
    get(size-1)
}
println("반환값 with = $lastItemWith")

반환값 let = 3
반환값 run = Run
반환값 with = With

세 함수 모두 리스트 배열이 출력되는게 아니라 마지막 코드인 count() , get(size-1) 를 따라 반환값을 출력했다.

let = ["Scope", "Function", "Run"] 으로 길이가 3이라서 3이 출력되었고,

run과 with 모두 add 스택이 무시되고(자기 자신을 돌려받지 못하기 때문에), 각각 마지막으로 추가된 Run 과 With가 get 메서드를 통해 불러와진 모습이다.

profile
이수용

0개의 댓글