【问题标题】:What is the reason this type parameter syntax doesn't compile?这种类型参数语法无法编译的原因是什么?
【发布时间】:2013-08-06 06:34:12
【问题描述】:

说我有:

class Class[CC[A, B]]
class Thing[A, B <: Int]
class Test extends Class[Thing] // compile error here

我得到编译器错误:

类型参数的种类 (cspsolver.Thing) 不符合 Class 类中类型参数的预期种类 (CC 类型)。 cspsolver.
Thing 的类型参数与类型 CC 的预期参数不匹配:类型 C 的边界 :Nothing

但是,当我修改代码使其看起来像这样时:

class Class[CC[A, B]]
class Thing[A, B] {
  type B <: Int
}
class Test extends Class[Thing]

它编译得很好。它们在功能上不是等效的吗?

【问题讨论】:

  • 在最后一个示例中,您有类型参数B 和类型成员B。它们具有相同的名称(因此只有一个可见),但它们并不相同。
  • @senia,有没有用同名有用的情况?
  • @huynhjl:我猜没有。但在某些情况下,阴影很有用:您可以重用名称。在隐式的情况下,还有一些部分有用的阴影滥用:参见this answer
  • @senia 你应该把你的评论变成一个答案,这样它才能被接受。你有正确的答案,而且很简单。
  • @Jean-PhilippePellet:谢谢,但这不是答案。我已经解释了为什么最后一个代码示例可以编译,但没有解释为什么第一个不编译。

标签: scala generics types scala-2.10


【解决方案1】:

原因在编译器消息中给出。在Class 中,您需要一个不受限制的CC,而Thing 有第二个类型参数必须是&lt;: Int 的限制。一种可能性是向Class 添加相同的约束,如

class Class[CC[A,B <: Int]]
class Thing[A, B <: Int]
class Test extends Class[Thing]

【讨论】:

  • 我不清楚为什么这个限制是到位的;为什么编译器不能在下限处调和两者?
【解决方案2】:

详细阐述 Petr Pudlák 的解释,这是我假设发生的情况:编译器尝试将 CC[A, B]Thing[A, B &lt;: Int] 统一起来。根据CCB的声明,B的上界为Any,被选为实例化B。但是,Thing 中的 B 应该具有 Int 的上限类型绑定,因此编译器会失败并显示您收到的错误消息。

为了保持类型系统的健全性,这是必要的,如下图所示。假设Thing 定义了一个依赖于它的B &lt;: Int 的操作,例如,

class Thing[A, B <: Int] {
  def f(b: B) = 2 * b
}

如果您将Class 声明为

class Class[CC[A,B]] {
  val c: CC
}

Test 一样

class Test extends Class[Thing] {
  val t: Thing
}

没有编译器抱怨,那么您可以进行以下调用

new Test().t.f(true)

这显然不安全。

【讨论】:

  • 我不相信你有一个有效的例子来说明为什么“允许这样的类型约束编译”会失败..但因为它甚至不会编译,所以我很难确定为什么错了!
  • 但无论如何我都会尝试:def f(b:B)...B &lt;: Int 的上下文中。所以我不买任何情况下f(true) 可能编译。
  • 我不确定我是否理解为什么new Test().t.f(true) 不会在编译时被捕获。在Testt 的类型不需要类型参数吗?如果它确实不会new Test().t 返回Thing[A, B &lt;: Int],这样编译器就会知道new Test().t.f 接受B &lt;: Int 并且Boolean 不是&lt;: Int
  • @RichardSitze @eddiemundorapundo 我的思路如下:如果编译器在... extends Class[Thing] 中选择Any, Any 作为Thing 的缺失参数,因为Class[CC[A,B]] 中的A,B 没有明确的参数上限,如果编译器没有引发错误,则有效val t: Thing[Any, Any],因此f(b: Any)Test().t.f(true) 这样就可以了。当然,由于它不能编译,而且我们(至少,我)手头没有正式的 Scala 类型规则,所以很难说它是否真的会以这种方式工作。
猜你喜欢
  • 2016-10-18
  • 1970-01-01
  • 2019-07-08
  • 2016-01-21
  • 2010-09-17
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 2012-12-16
相关资源
最近更新 更多