I have the following generic case class to model a resources in an HTTP API (we use Akka HTTP):
case class Job[Result](
id: String,
result: Option[Result] = None,
userId: String,
)
and want to specify multiple, named, variations of a Job
, were some of them provide a result, while others don't:
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?*/]
my question is, is there any way to define Job
as a generic case class where the type parameter only needs to be specified when the field result
is Some
? What I would like to do is something like:
// result is by default None in Job, so I don't want to specify any type here
case class BarJob = Job
Or perhaps there's better ways to do this, rather than using type aliases?
CodePudding user response:
One option is to use base trait
s for Job
s with and without results:
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
You can then use match
on a Job
to see whether it has a result or not.
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")
}
This assumes that the result
is not actually optional.
CodePudding user response:
As pointed out in the comments, the Option
is "unnecessary".
I submit, it's not so much "unnecessary" as indicative ... of a way for you to implement what you want without repetitive declarations.
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]