오늘도 더 나은 코드를 작성하였습니까?

연산자 오버로딩과 기타 관례(구조 분해 선언과 component 함수) 본문

Kotlin in Action/코틀린 답게 사용하기

연산자 오버로딩과 기타 관례(구조 분해 선언과 component 함수)

hik14 2020. 8. 24. 22:05

구조 분해 선언(destructuring declaration)

복합적인 값을 분해해서 여러 다른 변수를 한꺼번에 초기화할 수 있다.

data class Point(val x: Int, val y: Int)

fun main() {
    val p = Point(10,20)
    val  (x, y) = p
    println(x)
    println(y)
}

내부에서 구조 분해 선언은 관례를 사용한다.

구조 분해 선언의 각 변수를 초기화하기 위해 componentN이라는 함수를 호출한다.

N은 구조 분해 선언에 있는 변수 위치에 따라붙는 번호다.

 

val (a, b) = p  ------> val a = p.component1() val b = p.component2()

 

data 클래스의 주 생성자에 들어있는 프로퍼티에 대해서는 컴파일러가 자동으로 componentN 함수를 생성한다.

 

데이터 클래스가 아니라면

class Point(val x: Int, val y: Int){
    operator fun component1() = x
    operator fun component2() = y
}

구조 분해 선언은 함수에서 여러 값을 반환할 때 유용하다.

여러 값을 한꺼번에 반환해야 하는 함수가 존재하면 모든 값이 들어갈 데이터 클래스를 정의하고

함수의 반환타입을 그 데이터 클래스로 변경한다면 가능하다.

 

예제

data class NameComponents(val name: String, val extension: String)

fun splitFileName(fullName: String): NameComponents{
    val result = fullName.split('.', limit = 2)
    return NameComponents(result[0], result[1])
}

fun main() {
    
    val (name, ext) = splitFileName("helloKotlin.kt")

    println(name)
    println(ext)
}

 

배열이나 컬렉션에도 componentN 함수가 존재한다.

코틀린 표준 라이브러리는 맨 앞 원소 5개에 대해서 componentN을 제공한다.

fun main() {

    val list = listOf<String>("A","B","C","D","E")

    val (a,b,c,d,e)  = list

    println(a)
    println(b)
    println(c)
    println(d)
    println(e)
}

 

Pair 또는 Triple 클래스를 이용한다면 함수에서 여러값을 더 간단하게 반환가능하다.

 

구조 분해 선언과 루프

함수 본문 뿐아니라 변수 선언이 들어갈 수 있는 장소라면 어디든 구조 분해 선언을 사용할수있다.

특히, map 원소에 대해 이터레이션 할때 구조 분해선언은 매우 유용하다.

fun printEntries(map: Map<String, String>){
    for ((key, value) in map)
        println("$key -> $value")
}

fun main() {

    val map = mapOf("Oracle" to "java", "JetBrains" to "kotlin")
    printEntries(map)
}