【问题标题】:Why Int, Double and Nothing 's common super type is AnyVal为什么 Int、Double 和 Nothing 的常见超类型是 AnyVal
【发布时间】:2015-01-05 12:15:53
【问题描述】:
scala> def b(x:Int) = { x match { case 1 => 1; case 2 => 3.5; case k => throw new Exception("Nothing")}} 
b: (x: Int)AnyVal
scala> def c(x: Int) = if (x == 1) 1 else if (x == 2) 3.5 else throw new Exception("Nothing")
c: (x: Int)Double

这是我从 REPL 得到的。为什么 Scala 编译器将函数 b 的返回类型视为 AnyVal。我认为应该是Double。 任何指向都会有所帮助。

【问题讨论】:

  • Double 不是Int 的超类型——它们之间最具体的常见超类型是AnyVal
  • @Lee 这是真的,但Int 通常会隐式转换为Double。在这种情况下,第三个 case 的存在会引发类型推断。
  • @Dima,感谢您的帮助!我仍然想知道为什么throws 子句会停止将Int 隐式转换为Double

标签: scala types inference


【解决方案1】:

Nothingevery 类型的子类型(参见Scaladoc)。这是允许诸如

之类的表达式所必需的
val x : Int = ???

IntDouble 最不常见的超类型是 AnyValNothing,是任何事物的子类型(包括AnyVal),因此不会改变推断的类型。

【讨论】:

  • 这在技术上是正确的,但有点误导:虽然 Int 和 Double 的常见超类型确实是 AnyVal,但类型推断失败的原因是带有 throw 子句的第三个 case。没有它,Int 被隐式转换为Double,并且Double 返回类型被正确推断。奇怪的是,用3 替换3.5 也会将推断类型更改为Int
  • 最后一点并不令人惊讶——当然IntIntNothing 的共同超类型是Int
  • @misberner 抱歉,我没有清楚地说明我的问题。当第三种情况被删除时,类型推断可以推断出返回类型为Double
  • @Dima 我看不出如何将 AnyVal 推断为 Int 的最不常见的超类型,而将 Double 推断为失败,这对我来说似乎完全正确。
  • @stew 我认为如果我们看不到定义此函数的上下文,我们无法判断它是否失败。请看函数c?推断为Double
【解决方案2】:

如果您需要以这种方式对待它,您可以将其声明为def b(x:Int): Double。 没有它,编译器会被throws 子句弄糊涂,并错误地推断出类型。类型推断并不完美,有时你必须帮助魔术:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-09
    • 2019-10-24
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 2015-09-06
    • 1970-01-01
    相关资源
    最近更新 更多