Scala 为“trait”定义“copy”`
鉴于: 我在Scala 为“trait”定义“copy”`,scala,Scala,鉴于: 我在X特征中定义了copy方法: sealed trait X { val x: String } case class A(x: String) extends X case class B(x: String) extends X 然而,我认为我可以做得更好,也就是说更精确 因为从技术上讲,仅仅因为输入了A,就可以输出B,因为AB是X的子类 所以我试着: def copy(x: X, newValue: String): X = x match { case A(_) =>
X
特征中定义了copy
方法:
sealed trait X { val x: String }
case class A(x: String) extends X
case class B(x: String) extends X
然而,我认为我可以做得更好,也就是说更精确
因为从技术上讲,仅仅因为输入了A
,就可以输出B
,因为AB
是X
的子类
所以我试着:
def copy(x: X, newValue: String): X = x match {
case A(_) => A(newValue)
case B(_) => B(newValue)
}
def COPYBERTER[T A(新值)
案例B()=>B(新值)
}
但是,我有编译时错误:
def copyBetter[T <: X](x: T, newValue: String): T = x match {
case A(_) => A(newValue)
case B(_) => B(newValue)
}
:17:错误:类型不匹配;
发现:A
必填项:T
案例A()=>A(新值)
^
:18:错误:类型不匹配;
发现:B
必填项:T
案例B()=>B(新值)
^
如何使用给定的签名实现
copyBetter
?我建议如下:
<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)
^
def COPYBERTER[T A(新值)
案例B()=>B(新值)
}
您返回的不是T
,而是X
a
和B
扩展X
而不是T
请尝试使用此签名:
def copyBetter[T <: X](x: T, newValue: String): X = x match {
case A(_) => A(newValue)
case B(_) => B(newValue)
}
def copyBetter[TSimple-当返回类型不包含在方法体中时,您如何期望它是T
。T
是不相关的,返回类型是A
和B
的共同祖先
此外,您不应该将其定义为:
def copyBetter[T <: X](x: T, newValue: String): X = // ...
使用此签名(忽略null
)实现方法的唯一方法是def copyBetter[T我想我也遇到了类似的问题,我解决了它,返回X
,这里的问题是,您的返回类型是动态的,在调用之前,您无法确定T
将是哪种类型,这与普通的泛型方法调用略有不同,在这种情况下,您可以事先指定类型,因为您知道我会看看Shapess,看看你的问题是否与之对应。谢谢这个有用的答案。我接受了佐尔坦的答案,因为他提前一分钟回答。和佐尔坦的答案一样:用这个代替原始的副本
,绝对没有好处。从那以后就没有好处了如果参数的类型为X
,则始终可以传递X
的子级。换句话说,约束除了简单地编写X:X
,没有添加任何其他内容。现在,在这个工作示例中,copyBetter
仍然可以接受a
,但返回aB
。尽管定义不正确理性,我认为,它是编译的。没有办法提高一个级别,也就是说,需要一个X
的输入子级,并将该子级作为输出?编译器无法知道运行时匹配哪种情况X
,所以它会选择最具体的超类型,即X
。我认为没有办法解决这个问题。Doe它实际上是编译的吗?\u我删除了复选框,因为Alexey是对的。我只是得到了同样的编译时错误:错误:未绑定通配符类型
@KevinMeredith编辑但同意,他的回答是第一个正确的:)因为存在单例类型
你能说得更多或者给我一个链接吗?单例类型是什么e
?x.type
在示例中是一个单例类型。该类型正好有两个值:x
和null
。
def copy(newValue: String): X = this match {
case _: A => A(newValue)
case _: B => B(newValue)
}
val x = A(1)
val y: x.type = copyBetter[x.type](x, 2)