본문 바로가기
Kotlin

[Kotlin] 코틀린 표준 라이브러리 let(), also(), apply(), run(), with() - (1)

by Taehyung Kim, dev 2020. 7. 22.
728x90

https://thkim-study.tistory.com/7 - also() 함수

https://thkim-study.tistory.com/8 - apply(), run(), with() 함수

 

람다식을 사용하는 코틀린의 표준 라이브러리에서 let(), apply(), with(), also(), run() 등 여러가지 표준함수가 있다.
이 표준 함수를 활용하여 복잡한 코드를 단순화하고 효율적으로 만들 수 있다.

 

 

함수의 람다식 접근 방법

 

함수 이름 람다식 접근 방법 반환 방법
let it block 결과
also it it
apply this this
run this block 결과
with this Unit

 

let() 함수

let() 함수는 함수를 호출하는 객체 T를 이어지는 block의 인자로 넘기고 block의 결괏값 R을 반환한다.

아래 예시로 확인해보자.

 

    // 일반적인 null 검사
    fun checkScore() {
        if (score != null) {
            println("Score: $score")
        }
    }

    // let 함수를 사용해 null 검사를 제거
    fun checkScoreLet() {
        score?.let { println("Score: $it") } // 1.
        val str = score.let { it.toString() } // 2.
        println(str)
    }
    checkScore()
    checkScoreLet()

 

  1. score에 let 함수를 사용했는데 매개변수가 람다식 하나일 때는 let({ ... })에서 표현이 소괄호가 생략되어 let{ ... }과 같이 작성할 수 있다.
    score?.처럼 null에서 안전한 호출을 위해 세이프 콜(?.)을 사용하였다.
    만약 scorenull일 경우 람다식 구문은 수행되지 않는다.
    null이 아니라면 자기 자신의 값 scoreit으로 받아서 처리할 수 있다.

  2. toString을 사용해 it을 문자열로 변환한 후 반환된 값을 str에 할당한다.
    이때 세이프 콜(?.)을 사용하지 않았는데, 만약 scorenull이라면 str에는 null이 할당된다.

    세이프 콜(?.)을 사용하더라도 람다식을 사용하지 않게 되므로 strString?으로 추론되어 null이 할당된다.

 

let() 함수 활용

아래는 안드로이드에서 Padding 값 지정 예시 상황이다.

 

val padding = TypedValue.applyDimension(
		TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics).toInt()
        
setPadding(padding, 0, padding, 0) // 좌, 우 padding 설정

TypedValue.applyDimension()을 통해 얻은 값을 정수형으로 변환 후 padding에 할당했다.
이때 padding이 한번만 사용되면 변수 할당을 하느라 자원 낭비가 있을 수 있으므로 let() 함수를 활용할 수 있다.

 

TypedValue.applyDimension(
		TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics).toInt()
        	.let { padding -> setPadding(padding, 0, padding, 0) }
            // 계산된 값을 padding이라는 이름의 인자로 받음

여기서 얻은 값을 let()을 통해 람다식으로 보내고 본문 코드에서 setPadding() 함수를 호출하여 값을 지정하고있다.
따로 변수를 할당할 필요가 없다 !!
아래는 더욱 간략화한 코드이다.

 

TypedValue.applyDimension(
		TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics).toInt()
        	.let { setPadding(it, 0, it, 0) }
            // padding 대신 it 사용

위와 같이 인자가 1개밖에 없으므로 it으로 간략화할 수 있다.

 

 

null 가능성이 있는 객체에서 let() 함수 활용

let()함수와 세이프 콜(?.)을 같이 사용하면 if (exam != null) 구문을 대체할 수 있다.

var obj: String? // null 가능성이 있는 변수 obj

if (obj != null) {
	// Do Something
}

위 코드를 let() 함수를 사용하여 변경해보자.

 

var obj: String?

obj?.let {
	// Do Something
}

상당히 간단해졌다.

else 문을 추가한다면?

 

val obj1: String?
var obj2: String

// if문을 사용한 경우
if (obj1 != null) {
	/* Do Something one */
} else {
	/* Do Something two */
}

위와 같은 코드는

 

val obj1: String?
var obj2: String

// let을 사용한 경우
obj?.let { /* Do Something one */ } ?: /* Do Something two */

이렇게 단순하게 변경 가능하다.

 

 

메서드 체이닝을 사용할 때 let()함수 활용

메서드 체이닝이란.

  • 여러 메서드 혹은 함수를 연속적으로 호출하는 기법

예시로 바로 확인해보자.

 

var a = 1
var b = 2

a = a.let { it + 2 }.let {
  val i = it + b
  i // 마지막 식 반환
}
println(a) // 5

두번째 let()의 람다식 마지막 구문이 반환되어 a재할당된다.

 

let() 함수가 유용해도 코드의 가독성을 고려한다면 많이 사용하는 것은 권장하지 않는다고 한다.

 

 

728x90

댓글