我尝试在特征中使用协变类型参数来构造一个case类,如下所示:
trait MyTrait[+T] {
private case class MyClass(c: T)
}编译器说:
error: covariant type T occurs in contravariant position in type T of value c然后我尝试了以下方法,但也不起作用:
trait MyTrait[+T] {
private case class MyClass[U <: T](c: U)
}这次的错误是:
error: covariant type T occurs in contravariant position in type >: Nothing <: T of type U有人能解释一下为什么T在这里处于协变的位置,并为这个问题提出解决方案吗?谢谢!
发布于 2012-03-08 23:15:26
这是面向对象编程的一个基本特性,但没有得到应有的重视。
假设您有一个集合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的超类,并且该方法可以工作。(但是,您必须更改您的方法才能处理这些事情。)
对于case类,除非您将其设置为不变,否则更难获得正确的结果。我建议这样做,并将泛型和变量推到其他地方。但我需要看到更多细节,以确保这将适用于您的用例。
发布于 2012-03-08 23:33:26
就快到了。这里:
scala> trait MyTrait[+T] {
| private case class MyClass[U >: T](c: U)
| }
defined trait MyTrait这意味着MyClass[Any]对所有T都有效。这就是为什么人们不能在那个位置使用T的根本原因,但是演示它需要更多的代码,而不是我现在想要的。:-)
https://stackoverflow.com/questions/9619121
复制相似问题