Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为“trait”定义“copy”`_Scala - Fatal编程技术网

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
,因为A
B
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
,但返回a
B
。尽管定义不正确理性,我认为,它是编译的。没有办法提高一个级别,也就是说,需要一个
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)