본문 바로가기

프로그래밍 언어/코틀린_Kotlin_더파기

Kotlin더파기_09_표준함수

표준함수는 코틀린 라이브러리에 있는 내장함수 및 확장함수(extension function)다.

확장함수를 사용하면 Type을 변경하지 않고 새 기능을 추가할 수 있다.

lambda(람다)를 인자로 받아서 동작한다.

 

apply

 

객체를 구성할 때 반복을 줄일 수 있다.

예를 들어 텍스트 파일을 사용하기 위해 File객체를 생성하고 읽기,쓰기,실행 속성을 만든다고 하자.

File객체를 구성하는 함수들을 호출할 때 참조변수(menuFile)를 사용한다.

 

val menuFile = File("menu_file.txt")

menuFile.setReadable(true)

menuFile.setWritable(true)

menuFile.setExecutable(false)

 

apply함수를 사용하여 다음과 같이 바꿀수 있다.

 

val menuFile = File("menu_file.txt).apply {

    setReadable(true)

    setWritable(true)

    setExecutable(false)

}

 

File객체를 구성하는 함수들을 apply람다에 넣어 반환한다.

이때 apply는 참조를 대체한다.

 

let

 

반복을 줄이는 또 다른 함수이다.

예를 들어 리스트의 첫번째 요소(2)의 제곱을 구한다고 하자.

 

val firstNumber = listOf(2,4,6).first()

val firstNumberSquared = firstNumber * firstNumber

 

이것을 let 함수를 이용하면 인자로 전달받아 람다를 실행하고 반환할 수 있다.

let의 인자로 전달된 람다는 호출된 객체의 참조만 인자로 받기 때문에 it 키워드를 사용할 수 있다.

 

val firstNumberSquared = listOf(2,4,6).first().let {

    it * it

 

또한 let은 null가능 타입에서 발생하는 예외를 방지할 수 있다.

 

예를 들어 null 가능 String타입의 변수를 호출한다고 하자.

예약손님과 그렇지 않은 손님에게 메세지를 다르게 해서 반환하는 함수를 만든다.

 

fun Greeting(reservedGuest : String?) : String {

    return if (reservedGuest != null) {

    " 안녕하세요, $reservedGuest. 이쪽으로 오세요"

    } else {

        "안녕하세요, 잠시만 기다리세요."

    }

}

 

return문에서 안전호출 연산자를 사용하여 reservedGuest가 null이 아닐때만 호출된다.

 

fun Greeting(reservedGuest : String?) : String {

    return reservedGuest?. let {

    " 안녕하세요, $it. 이쪽으로 오세요"

    } ?: "안녕하세요, 잠시만 기다리세요."

}

 

apply와 let의 차이점

apply는 대체만 하고 let은 전달한다.

apply는 람다 실행이 끝나면 객체를 반환하고 let은 람다의 마지막 코드의 실행 결과를 반환한다.

 

run

 

apply와 비슷하지만 apply처럼 객체를 반환하지 않는다.

 

아래는 menu_file.txt 텍스트 파일 내용에 "Egg Sandwich" 라는 문자열이 있는지 검사하는 코드이다.

 

val menuFile = File("menu_file.txt")

val searchEggSandwich = menufile.run {

     readText().contains("Egg Sandwich")

 

텍스트를 읽는 readText함수는 연결된 File객체를 읽어 들여서 contains함수로 문자열이 포함되어 있는지 확인한다.

그리고 run은 람다 결과를 반환한다. 즉, 있으면 true, 없으면 false를 반환한다.

 

run을 함수 참조에 사용한 예는 다음과 같다.

여기에 사용자 이름이 10자 이상인지 검사한 후 true, false를 반환하는 함수가 있다.

 

fun nameIsLong(name: String) = name.length >= 10

nameIsLong("Albert")

nameIsLong("Albert Einstein")

 

nameIsLong함수를 호출하는 2줄을 run을 사용하면 다음과 같다.

 

"Albert".run(::nameIsLong)

"Albert Einstein".run(::nameIsLong)

 

별로 유용한 것 같지 않지만 아래와 같이 여러 개의 함수를 연결하여 호출할 때는 다음과 같이 할 수 있다.

 

9번줄에서 Boolean값으로 true값을 반환 받으면

10번줄에서 체크한 후 println으로 출력한다.

 

run을 사용하지 않고 표현하면 다음과 같다. 어느 것이 더 이해하기 쉬운가?

 

 

also

 

also는 let함수와 비슷하다.

다른 점은 람다의 결과를 반환하지 않고 전달받은 객체를 반환한다. 

 

 

takeIf , takeUnless

takeIf는 람다 조건식을 실행한 후 true면 받은 객체가 반환되고 false면 null이 반환된다.

takeUnless는 조건식을 실행한 후 false면 받은 객체가 반환되고 true면 null이 반환된다.