케이스 클래스

케이스 클래스(case class)는 일반 클래스와 조금 다른데, 불변 데이터 모델을 만드는데 유용하고, 다음 장에서 설명할 패턴 부합(pattern matching) 기능과 더불어 쓰기 좋습니다.

일반 클래스 앞에 case 키워드만 붙여 만듭니다.

case class Point(x: Double, y: Double)
case class Circle(point: Point, radius: Double)

val center = Point(0.0, 0.0)
val smallCircle = Circle(center, 1.0)
println(smallCircle.radius) // => 1.0

케이스 클래스는 new 키워드를 쓰지 않고도 인스턴스를 만들 수 있습니다. 케이스 클래스를 만들면 기본으로 apply 메서드가 만들어지고, 이 메서드로 인스턴스를 만들어 낼 수 있게 되기 때문입니다. 그리고, 스칼라에서 apply 메서드는 특별하게 .apply를 생략해 쓸 수 있습니다.

Circle(center, 1.0) == Circle.apply(center, 1.0) == new Circle(center, 1.0)

케이스 클래스 비교

일반 클래스의 기본 equals 메서드는 참조(reference)값이 동일한지 비교합니다. 그래서 보통은 equals 메서드를 재정의해서 원하는 방식으로 같은지 비교하곤 합니다.

케이스 클래스를 만들면, 담고 있는 값들을 기준으로 비교하는 equals 메서드가 자동으로 만들어집니다.

println(Circle(center, 1.0) == Circle(center, 1.0)) // => true
println(Circle(center, 1.0) == Circle(center, 2.0)) // => false

케이스 클래스 복제

케이스 클래스를 객체로 만들면, 만들 때 지정한 값은 val로 변수를 선언한 것과 마찬가지로 변경할 수 없습니다. 대신, 자동으로 만들어지는 copy 메서드를 써서 일부 값을 새로운 값으로 지정한 새 인스턴스를 만드는 방식을 씁니다.

val aCircle = Circle(Point(0.0, 0.0), 1.0)
val biggerCircle = aCircle.copy(radius = 2.0)
val movedCircle = biggerCircle.copy(point = Point(2.0, 2.0))

기존 인스턴스는 그대로 있고, 일부 속성만 새로운 값으로 바뀐 또 다른 인스턴스가 생성됩니다. 케이스 클래스는 기본적으로 불변(immutable)인 셈입니다.