我需要定义以返回扩展特征的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)
有什么想法要实现吗?
答案 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)
案例类实际上不是等效,例如-equals
和hashcode
将忽略< / 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]
为假),但仍可以在期望Person
和getValue
的地方使用。
答案 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} }方法