Dev/Kotlin

Kotlin 기본 개념 정리

healthyryu 2021. 3. 12. 12:24
반응형

Kotlin 기본 개념 정리를 시작해 본다. 후~~ 심호흡을 가다듬고...

 

일단, 코틀린의 핵심인

Scope functions - let, run, with, apply, also.

 

유용한 함수에 대한 자세한 설명은 코틀린 사이트에서 잘 나와있다.

kotlinlang.org/docs/scope-functions.html

 

Scope functions - Help | Kotlin

 

kotlinlang.org

아주 짧게 정리하자면,

1. 리턴 값의 차이

  - 람다 결과를 리턴 값으로 받는 let, run, with

  - 해당 객체 자체를 리턴 값으로 받는 apply, also

2. null 처리는 let

 

이렇게 간단하게 2가지로 개념을 이해하는게 편할것 같다. 그리고 하나씩 살펴보면 된다고 생각한다.

 

 

간단한 사용 방법

- Null이 아닌 객체 실행 : let

val str: String? = "Hello"   
//processNonNullString(str)       // compilation error: str can be null
val length = str?.let { 
    println("let() called on $it")        
    processNonNullString(it)      // OK: 'it' is not null inside '?.let { }'
    it.length
}

 

- Local Scope 에서 읽기 쉽게 변수명 변경 : let

val numbers = listOf("one", "two", "three", "four")
val modifiedFirstItem = numbers.first().let { firstItem ->
    println("The first item of the list is '$firstItem'")
    if (firstItem.length >= 5) firstItem else "!" + firstItem + "!"
}.toUpperCase()
println("First item after modifications: '$modifiedFirstItem'")

 

- 객체 구성하기 or 초기화 작업 : apply

val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
println(adam)

 

return 값 이라는 측면에서는 also 도 동일한 효과를 낸다.

 

 

- 객체 구성 및 결과 계산 : run

val service = MultiportService("https://example.kotlinlang.org", 80)

println(service.run{query(prepareRequest() + " to port $port")})

val result = service.run {
    port = 8080
    query(prepareRequest() + " to port $port")
}

println(result)

------ 결과 ------

기본 service     -> Result for query 'Default request to port 80'
run 적용 result  -> Result for query 'Default request to port 8080'
run 적용한 service 의 port 는 8080으로 변경

객체 구성 및 결과 값을 리턴하는 의미에서 run, with, let 모두 같은 결과를 가져온다.

 

- 식이 필요한 문을 실행할때 : 확장x run

val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"

    Regex("[$sign]?[$digits$hexDigits]+")
}

for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")) {
    println(match.value)
}

 

 

- 추가적인 효과를 낼때 : also

val numbers = mutableListOf("one", "two", "three")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("four")
    
----- 결과 -----

also 의 문장 출력 -> The list elements before adding new one: [one, two, three]
numbers 출력 -> [one, two, three, four]

여기서 결과값만 볼때 apply 를 사용해도 무방하나 표현상 also가 맞기에 사용한다는 개념 같다. 지정함수의 차이 말고는 다를게 없기 때문이다.

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply).
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#also).
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

 

- 객체에 있는 함수들을 그룹화 하기 위한 처리 : with

val numbers = mutableListOf("one", "two", "three")
println("$numbers")
println("${numbers.size}")

----- with 사용 -----

with(numbers) {
    println("'with' is called with argument $this")
    println("It contains $size elements")
}
반응형