Destructuring Declaration은 어떤 객체의 데이터를 변수들에 대입하는 기술입니다.
다음 코드를 보시면 이해가 빠릅니다.
data class Person(val name: String, val age: Int)
val person = Person("chacha", 10)
val (name, age) = person
person
객체는 name
과 age
라는 데이터를 갖고 있습니다.
이 데이터를 name
과 age
라는 변수 선언과 동시에 할당하고 있습니다.
코틀린이 이런 문법을 지원하지 않는다면 다음처럼 변수 할당 및 get
메소드로 초기화를 해주어야 합니다.
val name = person.name
val age = person.age
위의 두개의 코드들을 비교하시면 Destructuring Declaration
를 사용한 코드가 더 간결하고 가독성이 좋아 보입니다.
예제
Destructuring Declaration
는 다음과 같이 for 문에도 적용할 수 있습니다.
val persons = arrayListOf<Person>()
persons.add(Person("chacha", 10))
persons.add(Person("JS", 30))
for ((name, age) in persons) {
println("name: $name, age: $age")
}
만약 어떤 변수를 사용하지 않는다면, _
으로 생략할 수 있습니다. 미사용 변수를 생략하면 필요한 변수만 눈에 보이기 때문에 가독성이 좋아질 수 있습니다.
val (name, _) = person
println("name: $name")
for ((_, age) in persons) {
println("age: $age")
}
다음과 같이 map
에도 적용할 수 있습니다. 기존에는 it.name
처럼 접근해야 하지만 name
으로 변수를 선언하고 사용할 수 있습니다.
persons.map {
println("name: ${it.name}, age: ${it.age}")
}
persons.map { (name, age) ->
println("name: $name, age: $age")
}
원리
Person
클래스는 Data class
입니다. 데이터 클래스는 Destructuring Declaration
지원을 위해 몇몇 메소드를 자동으로 만들어줍니다.
data class Person(val name: String, val age: Int)
다음 코드를 자바로 변환해보면 어떤 메소드가 만들어지는지 어떻게 동작하는지 알 수 있습니다.
data class Person(val name: String, val age: Int)
val person = Person("chacha", 10)
val (name, age) = person
아래 코드는 위의 코틀린 코드가 자바로 변환된 코드입니다.
Person
클래스에 component1()
, component2()
라는 메소드들이 생성되고, 이 메소드들을 사용하여 변수들을 초기화하는 것을 알 수 있습니다.
public final class Person {
private final String name;
private final int age;
public Person(@NotNull String name, int age) {
this.name = name;
this.age = age;
}
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
}
Person person = new Person("chacha", 10);
String name = person.component1();
int age = person.component2();
String var4 = "name: " + name + ", age: " + age;
System.out.println(var4);
일반 클래스에 Destructuring Declaration 사용하기
데이터 클래스가 아닌 일반 클래스에서 Destructuring Declaration
를 사용하려면 componentN()
메소드들을 직접 구현하면 됩니다.
componentN()
에서 N
은 1부터 시작하며 변수에 대입되는 순서입니다.
중요한 것은 componentN()
은 operator 메소드로 구현되어야 합니다.
다음 위의 Data class
를 일반 클래스로 변경하였고, componentN()
메소드를 추가한 코드입니다.
class Person(val name: String, val age: Int) {
operator fun component1() : String = name
operator fun component2() : Int = age
}
val person = Person("chacha", 10)
val (name, age) = person
componentN()
을 정의하였기 때문에, Destructuring Declaration
을 사용할 수 있습니다.
주의
Destructuring Declaration
를 사용할 때 주의할 점은 componentN()
의 순서대로 대입이 되기 때문에, 다음과 같이 변수의 순서를 바뀌어도 할당되는 순서가 달라지지 않는다는 것입니다.
val person = Person("chacha", 10)
val (age, name) = person
println("name: $name, age: $age")
// name: 10, age: chacha
참고
Recommended Posts:
- Kotlin - Collections와 Sequences의 차이점
- Kotlin - Reified를 사용하는 이유?
- Kotlin - Sealed class 구현 방법 및 예제
- Kotlin - inline functions 이해하기
- KotlinTest로 Unit Test 작성하는 방법
- Kotlin - Collections 소개 및 사용법 정리 (List, Map, Set)
- Kotlin - Data class 이해 및 구현 방법
- Kotlin에서 자주 사용하는 annotation 정리
- Kotlin - Generics 클래스, 함수를 정의하는 방법
- Kotlin - lateinit과 Delegates.notNull의 차이점
- Kotlin - Delegates로 프로퍼티를 Observerable로 만들기
- Kotlin - Null을 안전하게 처리하는 방법 (Null safety, 널 안정성)
- Kotlin - lateinit과 lazy로 초기화를 지연하는 방법