返回扩展特征的案例类

时间:2018-07-27 19:43:51

标签: scala traits case-class

我需要定义以返回扩展特征的case类:

trait Id {
  def id: Long
}

case class Person(name: String)

val john = Person("John") 
val johnWithId: Person with Id = /*person -> 123L*/ ???

任何想法我该如何实现?

我正试图减少代码重复,这就是为什么我没有声明trait Person这样的原因:

trait Id {
  def id: Long
}

trait Person {
  def name: String
}

case class PersonWithoutId(name: String) extends Person

case class PersonWithId(name: String, id: Long) extends Person with Id

val john = PersonWithoutId("John")
val johnWithId: Person with Id = PersonWithId(person.name, 123L)

有什么想法要实现吗?

4 个答案:

答案 0 :(得分:3)

Person一旦实例化,就为时已晚-实例john实例化后就无法更改。但是,您可以实例化Person with Id

val johnWithId: Person with Id = new Person("John") with Id {
  override def id: Long = 123L
}

请注意,这与使用PersonWithId(name: String, id: Long)案例类实际上不是等效,例如-equalshashcode忽略< / em>此实现中的ID。

答案 1 :(得分:2)

val johnWithId: Person with Id = new Person("John") with Id { def id = 123L }

答案 2 :(得分:1)

一些回旋方式:

case class WithId[A](id: Long, value: A) extends Id
object WithId {
  implicit def getValue[A](x: WithId[A]): A = x.value
}

// elsewhere
val johnWithId = WithId(123, john)

johnWithId不会扩展Person(因此johnWithId.isInstanceOf[Person]为假),但仍可以在期望PersongetValue的地方使用。

答案 3 :(得分:0)

最正确的解决方案是

case class Person(name: String, id: Long) extends Id

理论上您可以做到的

val johnWithId: Person with Id = new Person("John") with Id { def id = 123L }

如安德烈(Andrey)所述,它不遵守整个case class合同,因为具有不同ID和相同名字的人是平等的,因为id不会用于{{1} }方法