Kotlin - Destructuring Declaration

Destructuring Declaration은 어떤 객체의 데이터를 변수들에 대입하는 기술입니다.

다음 코드를 보시면 이해가 빠릅니다.

data class Person(val name: String, val age: Int)

val person = Person("chacha", 10)
val (name, age) = person

person 객체는 nameage라는 데이터를 갖고 있습니다. 이 데이터를 nameage라는 변수 선언과 동시에 할당하고 있습니다.

코틀린이 이런 문법을 지원하지 않는다면 다음처럼 변수 할당 및 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

참고

Loading script...
codechachaCopyright ©2019 codechacha