lap*_*uli 31 scala covariance contravariance case-class
我试图在trait中使用covariant类型参数来构造一个case类,如下所示:
trait MyTrait[+T] {
private case class MyClass(c: T)
}
Run Code Online (Sandbox Code Playgroud)
编译说:
error: covariant type T occurs in contravariant position in type T of value c
Run Code Online (Sandbox Code Playgroud)
然后我尝试了以下但它也没有用:
trait MyTrait[+T] {
private case class MyClass[U <: T](c: U)
}
Run Code Online (Sandbox Code Playgroud)
这次的错误是:
error: covariant type T occurs in contravariant position in type >: Nothing <: T of type U
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么T在这里处于协变位置并建议解决这个问题吗?谢谢!
Rex*_*err 61
这是面向对象编程的一个基本特征,它没有得到应有的重视.
假设你有一个集合C[+T].那+T意味着,如果U <: T,那么C[U] <: C[T].很公平.但是成为子类意味着什么?这意味着每个方法都应该适用于原始类.所以,假设你有一个方法m(t: T).这表示你可以采取任何措施t并做一些事情.但C[U]只能做一些事情U,可能不是全部T!所以,你必须立即反驳你的主张C[U]是的子类C[T].事实并非如此.有些事情,你可以用一个做C[T],你不能用做C[U].
现在,你怎么解决这个问题?
一种选择是使类不变(删除+).另一个选择是,如果你接受一个方法参数,也允许任何超类:m[S >: T](s: S).现在如果T改变了U,那没什么大不了的:超类T也是一个超类U,并且该方法可行.(但是,您必须更改方法才能处理此类事情.)
对于一个案例类,除非你使它不变,否则更难做到正确.我建议这样做,并在其他地方推广泛型和方差.但我需要查看更多详细信息,以确保这适用于您的用例.
Dan*_*ral 13
差不多了.这里:
scala> trait MyTrait[+T] {
| private case class MyClass[U >: T](c: U)
| }
defined trait MyTrait
Run Code Online (Sandbox Code Playgroud)
哪种方式MyClass[Any]对所有人都有效T.这是为什么一个人不能T在那个位置使用的根本原因,但是证明它需要的代码比我现在的情绪要多.:-)