sealed trait vs. enum

Scala에서 sealed traitenum은 모두 여러 가지 값을 나타내는 타입을 정의하는 데 사용되지만, 구조용도에서 차이가 있습니다. 둘 다 Sum Type(합 타입)을 정의하는 데 쓰일 수 있지만, 세부적인 동작과 기능에서 차이를 보입니다. 이 차이를 더 명확히 하기 위해 각각을 살펴보겠습니다.

1. sealed trait:

sealed trait는 다양한 하위 타입들을 정의할 수 있는 추상적인 데이터 구조입니다. Scala에서 sealed 키워드는 해당 트레잇을 상속할 수 있는 타입들을 제한합니다. 즉, sealed가 선언된 트레잇을 상속받는 모든 하위 타입들은 같은 파일 내에서 정의되어야 합니다. 이는 컴파일러가 해당 트레잇을 상속하는 모든 타입을 알고 있어야만 하기 때문에, 패턴 매칭에서 컴파일러가 exhaustive check (모든 경우를 다루었는지 확인)를 할 수 있도록 돕습니다.

예시:

sealed trait Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal
case class Bird(name: String) extends Animal

2. enum:

Scala 3에서 도입된 enum열거형 타입을 정의하는 더 간결하고 제한적인 방식입니다. enum은 특정한 상태나 값들을 열거하는 데 사용되며, 간단한 Sum Type을 정의하는 데 적합합니다. 기존의 sealed trait + case class 패턴을 더 명시적이고 구조화된 방식으로 대체할 수 있습니다. enum은 기본적으로 고정된 선택지 목록을 나타내며, 그 자체로 더 직관적입니다.

예시:

enum Animal {
  case Dog(name: String)
  case Cat(name: String)
  case Bird(name: String)
}

주요 차이점:

특징 sealed trait enum
유연성 더 유연함: case class, object, 또 다른 sealed trait로 확장 가능 구조가 더 제한적: 각 경우는 enum 내에서 정의됨
복잡성 더 복잡한 데이터 구조를 표현할 수 있음 주로 간단한 상태나 값의 집합을 정의하는 데 사용
코드 구조 여러 파일에 걸쳐 하위 타입을 정의할 수 있음. 단, 같은 파일 안에서만 사용 가능 모든 경우는 한 파일에서 정의됨
패턴 매칭 패턴 매칭에서 모든 하위 타입을 다루도록 컴파일러가 보장 패턴 매칭에서 모든 경우를 다룰 수 있음
기본 제공 기능 별도의 부가 기능이 없음 enum은 추가적인 기능을 제공 (ex: 메소드, 열거 순서 등)

어느 것을 사용할지 선택하는 기준:

  1. 유연성이 필요할 때: 만약 다양한 하위 타입들이 서로 다른 필드나 동작을 가져야 한다면 sealed trait을 사용하는 것이 좋습니다. 예를 들어 복잡한 데이터 구조를 정의해야 하거나, 여러 파일에 걸쳐 타입을 확장하고 싶다면 sealed trait이 적합합니다.
  2. 간결하고 명시적인 열거가 필요할 때: enum은 명확하게 열거할 수 있는 고정된 선택지를 정의할 때 적합합니다. 복잡한 상속 구조가 필요 없고, 간단한 선택지들을 표현하고자 할 때 enum을 사용하는 것이 더 간단하고 명시적입니다.

결론적으로, **Scala 2에서는 sealed trait**로 Sum Type을 정의했지만, **Scala 3에서는 enum**을 사용하여 간결하고 더 명시적인 방식으로 열거형 타입을 정의할 수 있습니다.