Scala 如何在特征中定义一个方法以通用地返回子类

Rob*_*Jr. 1 scala

给定一个非常简化的模型,说明我要实现的内容:

sealed trait Data
case class CustomerData(values: List[String])
case class EmployeeData(values: List[String])
Run Code Online (Sandbox Code Playgroud)

我想在 trait 上定义一个方法,该方法要求每个 case 类定义一个方法,该方法返回一个带有附加字符串的新实例。以下似乎不起作用,它让我感到困惑,但我希望 T 不仅仅是我任何类型的数据,而是子类的实际类型:

sealed trait Data {
  def withNewValue[T <: Data](v : String) : T
}
Run Code Online (Sandbox Code Playgroud)

子类应该如下所示:

case class CustomerData(values: List[String]) {
  override def withNewValue[CustomerData](v : String) : CustomerData = CustomerData(v :: values)
}
Run Code Online (Sandbox Code Playgroud)

但这不会编译也不会限制覆盖要求类型是 CustomerData 而不是 EmployeeData 允许某人做一些愚蠢的事情,例如:

case class CustomerData(values: List[String]) {
  override def withNew[EmployeeData](v : String) : EmployeeData = EmployeeData(v :: values)
}
Run Code Online (Sandbox Code Playgroud)

我有什么想法可以实现我的目标吗?

Tza*_*har 5

一种方法是参数化特征本身,而不是方法:

sealed trait Data[T <: Data[T]] {
  def withNewValue(v : String): T
}

case class CustomerData(values: List[String]) extends Data[CustomerData] {
  def withNewValue(v : String): CustomerData = CustomerData(v :: values)
}
Run Code Online (Sandbox Code Playgroud)