// 구조 분해
>>> val p = Point(10, 20)
>>> val (x, y) = p
>>> println(x)
10
>>> println(y)
20
내부에서 구조 분해 선언은 다시 관례를 사용한다. 구조 분해 선언의 각 변수를 초기화하기 위해 componentN이라는 함수를 호출한다. 여기서 N은 구조 분해 선언에 있는 변수 위치에 따라 붙는 번호다.

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]) // 함수에서 데이터 클래스의 인스턴스를 반환한다.
}
>>> val (name, ext) = splitFilename("exmaple.kt")
>>> println(name)
example
>>> println(ext)
kt
배열이나 컬렉션에도 componentN 함수가 있음을 안다면 이 예제를 더 개선할 수 있다. 크기가 정해진 컬렉션을 다루는 경우 구조 분해가 특히 더 유용하다.
// 컬렉션에 대해 구조 분해 선언 사용하기
data class NameComponents {
val name: String,
val extension: String)
}
fun splitFilename(fullName: String): NameComponents [
val (name, extension) = fullName.split('.', limit=2)
return NameComponents(name, extension)
}
표준 라이브러리의 Pair나 Triple 클래스를 사용하면 함수에서 여러 값을 더 간단하게 반환할 수 있다. Pair와 Triple은 그 안에 담겨있는 원소의 의미를 말해주지 않으므로 경우에 따라 가독성이 떨어질 수 있는 반면, 직접 클래스를 작성할 피룡가 없으므로 코드는 더 단순해진다.
7.4.1 구조 분해 선언과 루프
함수 본문 내의 선언문뿐 아니라 변수 선언이 들어갈 수 있는 장소라면 어디든 구조 분해 선언을 사용할 수 있다. 예를 들어, 루프 안에서도 구조 분해 선언을 사용할 수 있다. 특히 맵의 원소에 대해 이터레이션할 때 구조 분해 선언이 유용하다. 다음 예제는 주어진 맵의 모든 원소를 출력하는 간단한 코드다.
// 구조 분해 선언을 사용해 맵 이터레이션하기
fun printEntries(map: Map<String, String>) {
for ((key, value) in map) { // 루프 변수에 구조 분해 선언을 사용한다
println("$key -> $value")
}
}
>>> val map = mapOf("Oracle" to "Java", "JetBrains" to "Kotlin")
>>> printEntries(map)
Oracle -> Java
JetBrains -> Kotlin
이 간단한 예제는 두 가지 코틀린 관례를 활용한다. 하나는 객체를 이터레이션하는 관례고, 다른 하나는 구조 분해 선언이다. 코틀린 표준 라이브러리에는 맵에 대한 확장 함수로 iterator가 들어있다. 그 iterator는 맵 원소에 대한 이터레이터를 반환한다. 따라서 자바와 달리 코틀린에서는 맵을 직접 이터레이션할 수 있다. 또한 코틀린 라이브러리는 Map.Entry에 대한 확장 함수로 component1과 component2를 제공한다. 앞의 루프는 이런 확장 함수를 사용하는 다음 코드와 같다.
for (entry in map.entires) { // Map.Entry에 대한 확장 함수로 component1과 component2를 제공
val key = entry.component1()
val value = entry.component2()
// ...
}
'Kotlin' 카테고리의 다른 글
[Kotlin in Action] 8.1 고차 함수 정의 (0) | 2025.03.27 |
---|---|
[Kotlin in Action] 7.5 프로퍼티 접근자 로직 재활용: 위임 프로퍼티 (0) | 2025.03.27 |
[Kotlin in Action] 7.3 컬렉션과 범위에 대해 쓸 수 있는 관례 (0) | 2025.03.27 |
[Kotlin in Action] 7.2 비교 연산자 오버로딩 (0) | 2025.03.26 |
[Kotlin in Action] 7.1 산술 연산자 오버로딩 (0) | 2025.03.26 |
댓글