处理重复案例的惯用方法 类

Idiomatic way to deal with Repetitive Case Classes

我正在学习案例 classes。据我了解,案例 classes 无法通过其他案例 classes 进行扩展。处理以下问题的惯用方法是什么:

我有两个案例 classes,A 和 B。它们是相同的,并提供给另一个案例 Class C。现在当我想定义一个“+”函数时,问题就出现了。这可以在下面看到:

object Example extends App {
  // repetitive case classes A and B - Can they be abstracted to one case class?
  case class A(a: Int, b: String) {
    def f1(): Unit = println(a, b)
  }
  case class B(a: Int, b: String) {
    def f1(): Unit = println(a, b)
  }

  case class C(a: A, b: B) {
    def serialize() = Map("a" -> a, "b" -> b)
    def +(new_a: A): C = C(new_a, b)
    def +(new_b: B): C = C(a, new_b)
  }
}

以上编译通过,但是很重复。如果我删除 case class B,只使用 case class A,我可以尝试做这样的事情:

// if I use the same type for both A and B, I cannot use + individually anymore
case class C_alt(a: A, b: A) {
  def serialize() = Map("a" -> a, "b" -> b)
  def +(new_a: A): C_alt = C_alt(new_a, b)
  def +(new_b: A): C_alt = C_alt(a, new_b)
}

但是,我现在不能同时拥有 A 和 B 的“+”函数,因为类型相同并且重载失败。

解决此代码重复问题的惯用 Scala 方法是什么?理想情况下,我希望有一个常见的案例 class 实现这些方法,并且 A 和 B 都扩展它。但是由于 case class 不允许由另一个 case class 扩展,我应该使用正常的 class 吗?

首先可以按照大家的建议使用普通的class。您可以使用 copy(为案例 类 提供)而不是您的 + 方法。

但是,如果您想获得免费的 case class 函数并且您有多种常见行为,那么您可以使用 trait 来抽象出您的类型的行为。

trait TDemo {
  def i: Int

  def s: String

  def f1(): Unit = println(i, s)

  def f2(): Int = i + 10

  def f3(): String = s + " LOL"

  def toString: String
}

case class Demo1(a: Int, b: String) extends TDemo
case class Demo2(a: Int, b: String) extends TDemo

trait TDemoWrapper[A <: TDemo, B <: TDemo] {
  def a: A

  def b: B

  def serialize() = Map("a" -> a, "b" -> b)
  
  def f1(): Unit = println(s"a :: $a, b :: $b")
}

case class DemoWrapper1(a: Demo1, b: Demo2) extends TDemoWrapper[Demo1, Demo2]
case class DemoWrapper2(a: Demo1, b: Demo1) extends TDemoWrapper[Demo1, Demo1]