Given this code:
object Testy extends App {
case class Person(
id: Option[Long],
firstName: String,
lastName: String,
address: Address)
case class Address(id: Option[Long],
name: String,
number: Int)
val personOrAddress:AnyRef= Person(Some(1L), "first", "last", Address(Some(1L), "street", 1))
type HasCopyMethodWithId = _
val newId = Some(123L)
personOrAddress.asInstanceOf[HasCopyMethodWithId].copy(id = newId)
}
How can I implement 'type HasCopyMethodWithId' so that this code compiles and does not fail in runtime?
I've tried:
type HasCopyMethodWithId = {def copy(id: Option[Long]): AnyRef}
The synthetic copy
method provided by case classes is one single method with all arguments of that case class, not an individual overloaded one for id
, firstName
etc. Therefore the structural type doesn't match.
You could add an auxiliary method:
case class Person(id: Option[Long],
firstName: String,
lastName: String,
address: Address) {
def copyId(newId: Option[Long]): Person = copy(id = newId)
}
case class Address(id: Option[Long],
name: String,
number: Int) {
def copyId(newId: Option[Long]): Address = copy(id = newId)
}
val personOrAddress: Any =
Person(Some(1L), "first", "last", Address(Some(1L), "street", 1))
type HasCopyMethodWithId = { def copyId(id: Option[Long]): Any }
val newId = Some(123L)
personOrAddress.asInstanceOf[HasCopyMethodWithId].copyId(id = newId)
But then almost certainly better is to provide a static type:
trait CopyWithId {
type Repr
def copyId(id: Option[Long]): Repr
}
case class Person(id: Option[Long],
firstName: String,
lastName: String,
address: Address) extends CopyWithId {
type Repr = Person
def copyId(newId: Option[Long]): Person = copy(id = newId)
}
case class Address(id: Option[Long],
name: String,
number: Int) extends CopyWithId {
type Repr = Address
def copyId(newId: Option[Long]): Address = copy(id = newId)
}
val personOrAddress: CopyWithId =
Person(Some(1L), "first", "last", Address(Some(1L), "street", 1))
val newId = Some(123L)
personOrAddress.copyId(id = newId)