Reputation: 23
I've got something like this:
trait ObjectId {
val value: Long
}
case class Room(id: Option[Room.Id])
case object Room {
case class Id(value: Long) extends ObjectId
}
case class Tree(id: Option[Tree.Id])
case object Tree {
case class Id(value: Long) extends ObjectId
}
What I want to do is create class FromDB
with field id, of type which extends trait ObjectId
and is nested inside T
:
case class FromDB[T](value: T, id)
for example it should work as follows:
FromDB[Room](Room, Room.Id)
FromDB[Tree](Tree, Tree.Id)
Upvotes: 0
Views: 642
Reputation: 103
You could use depenent types and let type inference work for you:
trait ObjectId {
val value: Long
}
trait Model[T] {
type Id <: ObjectId
}
case class Room(id: Option[Room.Id])
object Room extends Model[Room] {
case class Id(value: Long) extends ObjectId
}
case class Tree(id: Option[Tree.Id])
object Tree extends Model[Tree] {
case class Id(value: Long) extends ObjectId
}
case class FromDB[T, I <: Model[T]](value: T, id: I#Id)
val room = Room(Some(Room.Id(1)))
FromDB(room, room.id.get) // compiles
FromDB(room, Tree.Id(123)) // doesn't compile
Here, Model[T]
defines a type Id
which is constrained to be a child of ObjectId
. Each instance of Model[T]
has its own implementation of Id
.
In FromDB[T, I <: Model[T]]
, the compiler will infere I
if id
is an instance of the correct Model[T]
, it won't compile otherwise.
Upvotes: 1