I have two classes PixelObject
, ImageRefObject
and some more, but here are just these two classes to simplify things. They all are subclasses of a trait Object
that contains an uid.
I need universal method which will copy a case class instance with a given new uid
. The reason I need it because my task is to create a class ObjectRepository which will save instance of any subclass of Object
and return it with new uid
.
My attempt:
trait Object {
val uid: Option[String]
}
trait UidBuilder[A <: Object] {
def withUid(uid: String): A = {
this match {
case x: PixelObject => x.copy(uid = Some(uid))
case x: ImageRefObject => x.copy(uid = Some(uid))
}
}
}
case class PixelObject(uid: Option[String], targetUrl: String) extends Object with UidBuilder[PixelObject]
case class ImageRefObject(uid: Option[String], targetUrl: String, imageUrl: String) extends Object with UidBuilder[ImageRefObject]
val pix = PixelObject(Some("oldUid"), "http://example.com")
val newPix = pix.withUid("newUid")
println(newPix.toString)
but I am getting the following error:
➜ ~ scala /tmp/1.scala
/tmp/1.scala:9: error: type mismatch;
found : this.PixelObject
required: A
case x: PixelObject => x.copy(uid = Some(uid))
^
/tmp/1.scala:10: error: type mismatch;
found : this.ImageRefObject
required: A
case x: ImageRefObject => x.copy(uid = Some(uid))
^
two errors found
I would stick with the solution proposed by Seam. I have done the same a couple of months ago. For example:
trait Entity[E <: Entity[E]] {
// self-typing to E to force withId to return this type
self: E => def id: Option[Long]
def withId(id: Long): E
}
case class Foo extends Entity[Foo] {
def withId(id:Long) = this.copy(id = Some(id))
}
So, instead of defining an UuiBuilder with a match for all implementations of your trait, you define the method in your implementation itself. You probably don't want to modify UuiBuilder every time you add a new implementation.
In addition, I would also recommend you to use a self typing to enforce the return type of your withId() method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With