kyucumber
전체 글 보기

이펙티브 코틀린 아이템 37. 데이터 집합 표현에 data 한정자를 사용하라

데이터를 한꺼번에 전달해야 하는 경우 다음과 같은 클래스를 사용한다.

data class Player( val id: Int, val name: String, val points: Int )

data 한정자를 붙이면 아래와 같은 몇가지 함수가 자동으로 생성된다.

  • toString
  • equals와 hashCode
  • copy

    • copy는 immutable 데이터 클래스를 만들 때 편리하게 활용할 수 있다. copy는 객체를 얕은 복사 한다.
  • componentN

    • 위치를 기반으로 객체를 해제할 수 있다. 위치를 잘못 지정하면 큰 문제가 발생할 수 있으니 주의한다.

      val (id, name, pts) = player

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

데이터 클래스는 튜플보다 많은 것을 제공한다.

public data class Pair<out A, out B>( public val first: A, public val second: B ) : Serializable { /** * Returns string representation of the [Pair] including its [first] and [second] values. */ public override fun toString(): String = "($first, $second)" } public data class Triple<out A, out B, out C>( public val first: A, public val second: B, public val third: C ) : Serializable { /** * Returns string representation of the [Triple] including its [first], [second] and [third] values. */ public override fun toString(): String = "($first, $second, $third)" }

코틀린에 남아있는 튜플은 Pair와 Triple이 전부이다. 튜플은 좋아 보이지만 데이터 클래스를 사용하는것이 더 좋기 때문에 점차 없어졌다. 이는 몇가지 지역적인 목적으로 남아있다.

  • 값에 간단하게 이름을 붙일 때

    val (description, color) = when { degrees < 5 -> "cold" to Color.BLUE degrees < 23 -> "mild" to Color.YELLOW else -> "hot" to COLOR.RED }
  • 표준 라이브러리에서 볼 수 있는 것 처럼 미리 알 수 없는 aggregate(집합)을 표현할 때

    val (odd, even) = numbers.partition { it % 2 == 1 } val map = mapOf(1 to "San Francisco", 2 to "Amsterdam")

위 경우를 제외하면 데이터 클래스를 사용하는게 좋다.

예를 들어 fullname과 name을 나타내는 코드를 정의할 때 Pair<String, String>을 사용하면 해당 Pair가 전체 이름을 나타내는것을 인지하기 어렵다.

이를 데이터 클래스로 만들어도 큰 추가 비용이 들지 않으며 다음과 같은 장점이 있다.

  • 함수의 리턴 타입이 더 명확해진다.
  • 리턴 타입이 더 짧아지며 전달하기 쉬워진다.
  • 사용자가 데이터 클래스에 적혀있는 것과 다른 이름을 활용해 변수를 해제하면, 경고를 출력한다.

Reference

  • 이펙티브 코틀린 - 프로그래밍 인사이트, 마르친 모스칼라 지음, 윤인성 옮김

개인적인 기록을 위해 작성된 글이라 잘못된 내용이 있을 수 있습니다.

오류가 있다면 댓글을 남겨주세요.