首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么参数处于逆变量位置?

为什么参数处于逆变量位置?
EN

Stack Overflow用户
提问于 2012-03-08 22:22:59
回答 2查看 7.2K关注 0票数 32

我尝试在特征中使用协变类型参数来构造一个case类,如下所示:

代码语言:javascript
复制
trait MyTrait[+T] {
  private case class MyClass(c: T)
}

编译器说:

代码语言:javascript
复制
error: covariant type T occurs in contravariant position in type T of value c

然后我尝试了以下方法,但也不起作用:

代码语言:javascript
复制
trait MyTrait[+T] {
  private case class MyClass[U <: T](c: U)
}

这次的错误是:

代码语言:javascript
复制
error: covariant type T occurs in contravariant position in type >: Nothing <: T of type U

有人能解释一下为什么T在这里处于协变的位置,并为这个问题提出解决方案吗?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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类,除非您将其设置为不变,否则更难获得正确的结果。我建议这样做,并将泛型和变量推到其他地方。但我需要看到更多细节,以确保这将适用于您的用例。

票数 61
EN

Stack Overflow用户

发布于 2012-03-08 23:33:26

就快到了。这里:

代码语言:javascript
复制
scala> trait MyTrait[+T] {
     |   private case class MyClass[U >: T](c: U)
     | }
defined trait MyTrait

这意味着MyClass[Any]对所有T都有效。这就是为什么人们不能在那个位置使用T的根本原因,但是演示它需要更多的代码,而不是我现在想要的。:-)

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9619121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档