假设:
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
,因为B
是X
的子类。
所以我试过了:
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
?
答案 0 :(得分:1)
我建议如下:
def copyBetter[T <: X](x: T, newValue: String): X = x match {
case A(_) => A(newValue)
case B(_) => B(newValue)
}
答案 1 :(得分:1)
您没有返回T
而是X
。 A
和B
延伸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.type
是X
的子类型:
val x = A(1)
val y: x.type = copyBetter[x.type](x, 2)
y
类型表示y
必须与x
(或null
)相同。因为在您的实施中它不是,所以这种实现不适合签名。
答案 3 :(得分:0)
简单 - 如果返回类型甚至不涉及方法体,那么您期望返回类型为T
。 T
无关紧要,返回类型是A
和B
的共同祖先。
另外,不应该将其定义为:
def copy(newValue: String): X = this match {
case _: A => A(newValue)
case _: B => B(newValue)
}