본문 바로가기

Android/kotlin

[Effective Kotlin] Item No.37 데이터 집합 표현에 data 한정자를 사용하라

데이터 클래스

데이터를 한꺼번에 전달해야 할 때 data class를 쓰는데, class 앞에 data 한정자를 붙이면 몇 가지 함수가 자동으로 생성된다.

  • toString
  • equals와 hashCode
  • copy
  • compoentN(compoent1, component 2 등)

 

 

toString 함수는 클래스의 이름과 기본 생성자 형태로 모든 프로퍼티와 값을 출력해준다. 그래서 로그를 출력할 때나 디버그할 때 유용하다.

equals는 기본 생성자의 프로퍼티가 같은지 확인해준다. hashCode도 같은 결과를 낸다.

copy는 기본 생성자 프로퍼티가 같은 새로운 객체를 복제한다.

copy메서드는 data 한정자를 붙이기만 하면 자동으로 만들어져서 구현을 볼수도 볼필요도 없는데 대충 다음과 같을 것이다

 

위치를 기반으로 객체를 해제하는 건 장점도 있고 단점도 있다. 가장 큰 장점은 변수명을 원하는 대로 지정할 수 있다는 거다. 또한 componentN()만 있다면 List, Map.Entry 등의 형태로도 객체를 해제할 수 있다.

 

객체를 해제할 때는 주의해야 하므로 데이터 클래스의 기본 생성자에 붙어 있는 프로퍼티 이름과 같은 이름을 쓰는 게 좋다. 그렇게 하면 순서 등을 잘못 지정했을 때 인텔리제이, 안드로이드 스튜디오가 관련된 경고를 준다. 이런 경고는 유용하므로 경고 대신 오류로 업그레이드해도 좋다.
값을 하나만 갖는 데이터 클래스는 해제하지 않는 게 좋다. 간단한 코드지만 읽는 사람에게 혼동을 줄 수 있다. 특히 람다 표현식과 같이 활용될 때 문제가 된다.

 

튜플 대신 데이터 클래스 사용하기

 

데이터 클래스는 튜플보다 많은 걸 제공한다. 구체적으로 코틀린의 튜플은 Serializable을 기반으로 만들어지며 toString을 쓸 수 있는 제네릭 데이터 클래스다.

 

Pair, Triple만 예시로 든 이유는 이것이 코틀린에 남아 있는 마지막 튜플이기 때문이다. 과거엔 (Int, String, String, Long)처럼 괄호와 타입 지정을 통해 원하는 형태의 튜플을 정의할 수 있었다. 튜플은 데이터 클래스와 같은 역할을 하지만 훨씬 가독성이 나빴다. 튜플만 보고는 어떤 타입을 나타내는지 예측할 수 없다. 튜플은 좋아 보였지만 언제나 데이터 클래스를 쓰는 게 더 좋았기 때문에 점차 없어진 것이다. Pair, Triple은 몇 가지 지역적인 목적으로 인해 남아있을 뿐이다.

 

  • 데이터 클래스를 만든다 해도 추가비용은 거의 발생하지 않는다.
  • 함수의 리턴타입이 더 명확해진다.
  • 리턴 타입이 짧아지며, 전달하기 쉬워진다.
  • Pair의 값과 달리 data 클래스는 프로퍼티의 값을 명확하게 알 수 있다.
    • 성과 이름을 구분하기 쉽다.