带有可选字段的 Scala 通用案例 class

Scala generic case class with optional field

我有以下通用案例 class 来为 HTTP API 中的资源建模(我们使用 Akka HTTP):

case class Job[Result](
   id: String,
   result: Option[Result] = None,
   userId: String,
)

并想指定 Job 的多个命名变体,其中一些提供结果,而另一些不提供结果:

case class FooResult(data: String)
type FooJob = Job[FooResult]

// BarJob does not have any result, thus result should be None
case class BarJob = Job[/*what do to?*/]

我的问题是,有什么方法可以将 Job 定义为一般情况 class,其中仅当字段 result 为 [=17 时才需要指定类型参数=] ?我想做的是:


// result is by default None in Job, so I don't want to specify any type here
case class BarJob = Job

或者也许有更好的方法来做到这一点,而不是使用类型别名?

一种选择是将 traits 用于 Jobs 有和没有结果:

trait Job {
  def id: String
  def userId: String
}

trait JobWithResult[T] extends Job {
  def result: T
}

case class FooResult(data: String)
case class FooJob(id: String, userId: String, result: FooResult) extends JobWithResult[FooResult]

case class BarJob(id: String, userId: String) extends Job

然后您可以在 Job 上使用 match 来查看它是否有结果。

job match {
  case FooJob(id, userId, foo) => println(s"FooJob with result $foo")
  case j: JobWithResult[_] => println(s"Other job with id ${j.id} with result")
  case j: Job => println(s"Job with id {$j.id} without result")
}

这假设 result 实际上不是可选的。

正如评论中指出的那样,Option 是“不必要的”。

我提交,与其说它是“不必要的”,不如说是指示性的 ... 一种无需重复声明即可实现所需内容的方法。

  case class Job[Result](id: String, userId: String, result: Option[Result] = None)

  object Job { 
      def void(id: String, userId: String) = Job[Nothing](id, userId)
      def apply[R](id: String, userId: String, result: R) = Job(id, userId, Option(result))
   }

   type FooJob = Job[FooResult]
   type VoidJob = Job[Nothing]