데이터 클래스의 특성 중 convention 원리와 관련된 특성인 구조 분해 선언(destructuring declaration)에 대해 살펴보도록 하겠습니다.
데이터 클래스에 대한 기본적인 내용은 아래 포스팅을 참고하시면 됩니다. ^^
2020.03.03 - [코틀린] - 코틀린(Kotlin) - 데이터 클래스와 클래스 위임(by)
디스트럭쳐링(Destructuring)
구조 분해를 사용하면 객체가 가지고 있는 여러 값을 분해해서 여러 변수에 한꺼번에 초기화할 수 있습니다.
/* 구조 분해 간단한 예제 */
>>> val car = Car("현대", "그랜저 IG")
>>> val (manufacturer, model) = car //변수를 선언함과 동시에 car의 여러 컴포넌트로 초기화 합니다.
>>> println(manufacturer)
현대
>>> println(model)
그랜저 IG
구조 분해 선언은 일반 변수 선언과 비슷해 보이지만 "=" 의 좌변에 여러 변수를 괄호로 묶었다는 점에서 차이가 있습니다.
구조 분해 선언의 내부에서는 각 변수를 초기화하기 위해 componentN이라는 함수를 호출하게 되며, 여기서 N은 구조 분해 선언에 있는 변수 위치에 따라붙는 번호입니다.
즉, 앞에서 살펴본 val (manufacturer, model) = car 는 아래와 같이 컴파일됩니다.
데이터 클래스의 주 생성자에 들어있는 프로퍼티에 대해서는 컴파일러가 자동으로 componentN 함수를 만들어줍니다. 👍
다음 예제는 데이터 클래스가 아닌 일반 클래스에서 구현한 예제입니다.
/* 일반 클래스에서 구조 분해 선언하는 예제 */
class Car(val manufacturer: String, val model: String) {
operator fun component1() = manufacturer
operator fun component2() = model
}
이러한 구조 분해 선언은 함수의 리턴 값이 여러 개일 때 유용합니다.
반환할 모든 값이 들어갈 데이터 클래스를 정의하고 함수의 반환 타입을 이 데이터 클래스로 하면 됩니다!
구조 분해 선언을 통해 이런 함수가 반환하는 값을 쉽게 풀어서 여러 변수에 할당할 수 있습니다.
경우에 따라서 모든 값이 필요하지 않다면 사용되지 않는 값은 밑줄(_) 로 대체할 수도 있습니다.
val car = Car("현대", "그랜저", "그랜저 IG")
val (manufacturer, _, model) = car
>>> println("제조사 : ${manufacturer}, 모델 : ${model}")
이러한 구조 분해 선언은 무한하게 componentN을 선언할 수는 없고 맨 앞의 다섯 개 원소에 대해서만 componentN을 제공합니다.
이와 비슷한 기능으로는 코틀린 표준 라이브러리에 미리 정의된 Pair 나 Triple 클래스를 사용하면 함수에서 여러 값을 더 간단하게 반환할 수 있습니다.
Pair 나 Triple은 그 안에 담긴 원소의 의미를 겉으로는 알 수 없기 때문에 경우에 따라 가독성이 떨어질 수 있는 반면에, 직접 데이터 클래스를 작성할 필요가 없으므로 코드는 훨씬 더 단순해지고 간결해집니다.
/* Pair 예제 */
val pair = Pair("현대", "그랜저 IG")
>>> println(pair.first)
>>> println(pair.second)
또는
>>> println(pair.component1)
>>> println(pair.component2)
또는
val (manufacturer, model) = Pair("현대", "그랜저 IG")
>>> println(manufacturer)
>>> println(model)
/* Triple 예제 */
val triple = Triple("현대", "그랜저", "그랜저 IG")
>>> println(triple.first)
>>> println(triple.second)
>>> println(triple.third)
또는
>>> println(triple.component1)
>>> println(triple.component2)
>>> println(triple.component3)
또는
val (manufacturer, modelGroup, model) = Triple("현대", "그랜저", "그랜저 IG")
>>> println(manufacturer)
>>> println(modelGroup)
>>> println(model)
위와 같이 코틀린에서는 Pair(두 개의 값 반환), Triple(세 개의 값 반환) 을 제공해주고 있으며, 만약 4개 이상의 값을 반환하고자 한다면 그런 경우는 데이터 클래스를 만들고 그 클래스 객체를 반환하는 방식으로 사용하시는 것을 권장드립니다. ^^ 👍
구조 분해 선언과 루프
구조 분해는 변수 선언이 들어갈 수 있는 곳이라면 어디든 구조 분해 선언을 사용할 수 있습니다.
예를 들어 루프 안에서도 구조 분해 선언을 사용할 수 있습니다.
특히, Map의 원소나 List에 대해 이터레이션 할 때 구조 분해 선언이 굉장히 유용하게 사용됩니다.
/* 구조 분해 선언을 사용해 Map 이터레이션하기 */
val map = mapOf("JetBrains" to "Kotlin")
for((key, value) in map) { //루프 변수에 구조 분해 선언을 사용
println("${key} -> ${value}")
}
>>> JetBrains -> Kotlin
/* 구조 분해 선언을 사용해 List 이터레이션하기 */
val list = listOf("Android", "Kotlin", "Java")
for((index, element) in list.withIndex()) { //루프 변수에 구조 분해 선언을 사용
println("${index} -> ${element}")
}
>>> 0 -> Android
>>> 1 -> Kotlin
>>> 2 -> Java
'코틀린' 카테고리의 다른 글
코틀린(Kotlin) - 고차 함수 정의 (0) | 2021.05.19 |
---|---|
코틀린(Kotlin) - 프로퍼티 접근자 로직 재사용 : 위임 프로퍼티 (0) | 2021.04.27 |
코틀린(Kotlin) - 산술 연산자 오버로딩 (0) | 2021.04.20 |
코틀린(Kotlin) - 컬렉션과 배열 (0) | 2021.04.17 |
코틀린(Kotlin) - 원시 타입(primitive type) (0) | 2021.04.14 |