为`trait`定义`copy`

时间:2016-08-23 14:16:39

标签: scala

假设:

sealed trait X { val x: String }
case class A(x: String) extends X
case class B(x: String) extends X

我在copy特征中定义了X方法:

def copy(x: X, newValue: String): X = x match {
  case A(_) => A(newValue)
  case B(_) => B(newValue)
}

然而,我认为我可以做得更好,即准确。

因为从技术上讲,仅仅因为输入了A,所以可以输出B,因为BX的子类。

所以我试过了:

def copyBetter[T <: X](x: T, newValue: String): T = x match {
 case A(_) => A(newValue)
 case B(_) => B(newValue)
}

但是,我遇到了编译时错误:

<console>:17: error: type mismatch;
 found   : A
 required: T
          case A(_) => A(newValue)
                        ^
<console>:18: error: type mismatch;
 found   : B
 required: T
          case B(_) => B(newValue)
                        ^

如何使用给定的签名实现copyBetter

4 个答案:

答案 0 :(得分:1)

我建议如下:

def copyBetter[T <: X](x: T, newValue: String): X = x match {
  case A(_) => A(newValue)
  case B(_) => B(newValue)
}

答案 1 :(得分:1)

您没有返回T而是XAB延伸X但不延伸T

尝试使用此签名:

def copyBetter[T <: X](x: T, newValue: String): X = // ...

答案 2 :(得分:1)

使用此签名实现方法(忽略null)的唯一方法是def copyBetter[T <: X](x: T, newValue: String): T = x!为什么?因为存在单例类型。鉴于此签名,必须编译以下内容,因为x.typeX的子类型:

val x = A(1)
val y: x.type = copyBetter[x.type](x, 2)

y类型表示y必须与x(或null)相同。因为在您的实施中它不是,所以这种实现不适合签名。

答案 3 :(得分:0)

简单 - 如果返回类型甚至不涉及方法体,那么您期望返回类型为TT无关紧要,返回类型是AB的共同祖先。

另外,不应该将其定义为:

def copy(newValue: String): X = this match {
  case _: A => A(newValue)
  case _: B => B(newValue)
}