관리 메뉴

나만을 위한 블로그

[Kotlin] 범위 지정 함수(let, with, run, apply, also)란? 본문

개인 공부/Kotlin

[Kotlin] 범위 지정 함수(let, with, run, apply, also)란?

참깨빵위에참깨빵 2022. 5. 1. 23:47
728x90
반응형

공부하다 자꾸 나오는 키워드가 let과 apply라서 찾아보니 이것들은 범위 지정 함수고, 이것 말고도 3개가 더 있다고 한다. 징그럽게도 많네

그래서 이것들에 대해 정리하고자 한다. 늘상 그랬던 것처럼 일단 저 단어들의 사전적 정의부터 짚고 가자.

let : (~하게) 놓아두다, (~을 하도록) 허락하다, ~에게 ~시키다, ~하게 해 주다, ~할 것을 허용하다(allow to)
with : ~와 함께, ~을 가진, ~이 달린/붙은/있는, ~로, ~을 써서(이용하여)
run : 달리다(뛰다), 배달, 운행, 운항
apply : 지원하다, 쓰다, 적용하다, (페인트, 크림 등을) 바르다
also : 또한, 게다가, ~도

보면 알겠지만 이 단어들의 사전적 정의에는 공통점이 쥐뿔도 없다.

이번엔 범위 지정 함수에서 범위, 지정의 사전적 정의를 확인해보자.

범위 : 일정하게 한정된 영역, 어떤 것이 미치는 한계
지정 : 가리켜 확실하게 정함

사전적 정의를 바탕으로 범위 지정 함수의 뜻이 뭔지 생각해보면, 어떤 영역을 확실하게 정하고 거기서만 작동하는 함수? 라고 생각된다. 맞는지 코틀린 공식 홈페이지에서 확인해보자.

https://kotlinlang.org/docs/scope-functions.html

 

Scope functions | Kotlin

 

kotlinlang.org

코틀린 표준 라이이브러리엔 객체 컨텍스트 내에서 코드 블럭을 실행하는 것이 유일한 목적인 여러 함수가 포함돼 있다. 제공된 람다식을 써서 객체에서 이런 함수를 호출하면 임시 범위가 형성된다. 이 범위에선 이름없이 객체에 접근할 수 있다. 이런 함수를 범위 함수(Scope functions)라고 하며 let, run, with, apply, also의 5개가 있다.
기본적으로 이런 함수는 객체에 대해 코드 블럭을 실행한다. 다른 점은 이 객체가 블럭 안에서 사용 가능한 방식과 전체 표현식의 결과다.

객체 컨텍스트 안에서 코드 블럭을 실행하기 위한 함수라고 한다. 객체 컨텍스트는 무슨 말인가?

컨텍스트는 액티비티, 응용 프로그램의 정보를 얻거나 기능에 접근해 사용하기 위해 필요한 요소다. 이것의 객체 버전인가?

아래는 참고용으로 코틀린 공식 홈페이지에서 가져온 범위 지정 함수 별 설명이다. 너무 간결하긴 하다.

 

하지만 이걸 봐도 범위 지정 함수에 대해 내가 얻은 것은 없다. 그래서 국내 블로그들을 돌아다녀봤다.

 

https://velog.io/@huijiny/Kotlin-Scope-Function

 

Kotlin Scope Function

저는 이번 코틀린 스터디에서 다뤄본 범위 지정 함수에 대해서 써볼까 합니다. 저는 개인적으로 코틀린을 처음 사용해본 것이 이번년도 7월이었는데, 그 때 제대로 배우질 못해서, 좀 코틀린을

velog.io

범위 함수는 고차 함수로 정의된다. 즉, 다른 함수를 인수로 사용한다. 이런 인수는 특정 경우에 수신자와 함께 함수 리터럴로 나타날 수도 있다. 범위 지정 함수는 임의의 컨텍스트를 가져와 다른 scope로 넘긴다. 이 scope 안에선 함수에 따라서 it이나 this로 표현된다.

 

https://0391kjy.tistory.com/25

 

코틀린(Kotlin)의 Scope Function(let, with, run, apply, also) 정리

Scope Function 이라는 함수명에서 알 수 있듯이, 이 함수들을 람다식을 이용해서 호출하면 일시적인 Scope(범위)가 생기게 되고, 이 범위 안에서는 전달된 객체에 대해 "it" 또는 "this" 라는 Context Object

0391kjy.tistory.com

이 함수들을 람다식을 써서 호출하면 일시적인 scope(범위)가 생기고 이 범위 안에선 전달된 객체에 대해 it 또는 this라는 Context Object를 통해서 접근하게 된다
범위 함수에는 2가지 주요 차이점이 있다

- Context Object를 참조하는 방법(this, it)
- 리턴값

< Context Object : this 또는 it >

범위 함수 람다식 안에서 Context Object는 실제 객체명 대신 it 또는 this로 접근한다

this : run, with, apply / 람다식 안에선 일반 클래스 멤버처럼 사용 가능. this를 생략할 수 있지만 같은 이름의 멤버가 있을 경우 구별할 수 없어서 가급적 Context Object 안에선 this를 붙여 쓰는 게 좋다
it : let, also / 따로 전달 인자명을 지정할 수 있고 지정하지 않으면 기본적으로 it으로 접근한다

< 리턴값 >

apply, also : Context Object 그 자체를 리턴함. 그래서 체인 형식의 연속 호출이 가능하고 Context Object를 리턴하는 함수의 리턴문에도 사용 가능
let, run, with : 람다식 결과를 리턴함. 그래서 결과를 변수에 할당하거나 결과에 대해 추가 작업 등을 수행할 때 사용할 수 있다. 또는 리턴값을 무시하고 바로 람다식을 써서 임시 범위를 만들어 쓸 수도 있다

 

https://www.geeksforgeeks.org/kotlin-scope-function/

 

Kotlin - Scope Function - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

코틀린 표준 라이브러리에는 객체 컨텍스트 안에서 코드 블록을 실행하는 데 도움이 되는 여러 함수가 있다. 람다식을 써서 객체에서 이런 함수를 호출하면 임시 범위가 만들어진다. 이런 기능을 범위 기능(Scope Functions)이라고 한다. 이름 없이 이 함수의 객체에 접근할 수 있다

 

요는 이름 없이 어떤 객체에 접근해서 함수를 연속 호출할 수 있게 해주는 걸 범위 함수라고 하는 듯하다.

아래는 "코틀린 범위 함수"를 검색하면 나오는 이미지다. 한 방에 범위 함수들의 특징과 원형에 대해서 정리해놓아서 자주 보고 눈에 익히면 좋을 것 같다.

 

 

그럼 이 범위 함수는 왜 쓰는 것인가?

 

https://velog.io/@hwi_chance/Kotlin-Scope-Functions

 

[Kotlin] Scope Functions

Scope Functions에 관하여

velog.io

Scope Function의 일반적인 형태는 아래와 같다
Person("Alice", 20, "Amsterdam").let {
    println(it)
    it.moveTo("London")
    it.incrementAge()
    println(it)
}
만약 Scope Function을 쓰지 않는다면 위의 코드는 아래와 같이 작성돼야 한다
val alice = Person("Alice", 20, "Amsterdam")
println(alice)
alice.moveTo("London")
alice.incrementAge()
println(alice)
Scope Function은 새 기술 기능을 도입하진 않지만 코드를 보다 간결하고 읽기 쉽게 만들 수 있다

 

코드를 간결하고 읽기 쉽게 만들 수 있다가 핵심이다. 똑같은 객체에 여러 메서드를 수행할 때 범위 함수를 사용한다면

 

  • 해당 객체에 어떤 함수들을 적용하는지 알기 쉽다
  • 객체에 함수를 적용하는 부분이 어디에서 시작해서 끝나는지 알 수 있다

 

간단한 예시로는 안드로이드의 리사이클러뷰 적용 부분이 있겠다. 안드로이드에서 리사이클러뷰를 만들 때는 내가 만든 어댑터 적용 및 레이아웃매니저, setHasFixedSize() 적용 등 하나의 리사이클러뷰 객체에 적용하는 메서드들이 여러 개 있다.

이 때 recyclerview.apply {} 형태로 범위 지정 함수를 사용한다면 좀 더 직관적으로 내가 리사이클러뷰에 어떤 함수들을 적용하는지 더 보기 쉬워질 것이다.

하지만 리사이클러뷰를 적용하는 그 짧은 코드에 굳이 범위 함수를 적용해야 하는지는 좀 더 생각해봐야 할 것 같다. 하나의 객체에 적용해야 할 함수가 많아서, 또는 그 함수의 리턴값을 통해 별도 함수로 처리해야 하는 경우가 아니라면 범위 함수를 적용하는 게 의미가 있을까 싶다.

반응형
Comments