【问题标题】:Idiomatic way to deal with Repetitive Case Classes处理重复案例类的惯用方法
【发布时间】:2020-06-28 19:18:53
【问题描述】:

我正在学习案例课程。据我了解,案例类不能被其他案例类扩展。处理以下问题的惯用方法是什么:

我有两个案例类,A 和 B。它们是相同的,并输入到另一个案例类 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)
  }
}

上面是编译的,但是很重复。如果我删除案例类 B,只使用案例类 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 方法是什么?理想情况下,我希望有一个实现方法的通用案例类,并且 A 和 B 都扩展它。但是由于不允许通过另一个案例类扩展案例类,我应该使用普通类吗?

【问题讨论】:

  • 你应该使用普通类吗?这取决于您首先使用 case 类的原因。为数不多的便利功能中的哪一个使case 类对您的应用程序有吸引力?大多数(如果不是全部)都可以编码到普通类中。
  • 如果你想要不同的类型,你需要不同的类型。这不是案例类的问题,对于普通类,您会遇到同样的问题。如何使用正确的方法名称而不是 +setAsetB
  • 谢谢大家,我使用案例类的主要原因是因为它们很容易用 circe 之类的库进行序列化。我使用“+”作为函数,因为我只是在更新案例类中的字段,这实际上只是一个序列化后的 json 对象。我想我也可以使用 setA 和 setB 来避免整个问题
  • 顺便说一句,您可能想使用copy 方法。
  • 感谢@LuisMiguelMejíaSuárez - 这看起来很有用

标签: scala object functional-programming abstraction case-class


【解决方案1】:

按照大家的建议,首先你可以使用普通的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]

【讨论】:

    猜你喜欢
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2011-07-03
    • 2020-04-28
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    相关资源
    最近更新 更多