3
C:\Users\John>scala
Welcome to Scala version 2.9.2 (Java HotSpot(TM) Client VM, Java 1.6.0_32).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

scala> Map()
res4: scala.collection.mutable.Map[Nothing,Nothing] = Map()

Map()不使用关键字时,将调用来自相应伴随对象new的方法。apply但是 Scala 文档没有列出apply可变映射的方法(只提供apply了从映射中检索值的方法)。

为什么上面的代码仍然有效?

4

3 回答 3

5

它看起来像 scaladoc 中的错误。对象中有一个apply方法collection.mutable.Map(继承自GenMapFactory),但它没有出现在 Map 的文档中。此问题似乎已在升级 2.10 的文档中得到修复

注意:您必须查看对象文档,而不是第一类。当然,该方法适用applyclass现有的地图实例,并从中检索数据。

于 2012-07-21T16:29:45.803 回答
3

的伴随对象上有一个 apply() 方法scala.collection.immutable.Map()。它继承自scala.collection.MapFactory . 该方法采用可变数量的对参数,通常用作

Map("foo"->3, "bar"->4, "barangus"->5)

不带参数调用它显然也可以,但是比我聪明的人必须解释为什么类型推理引擎会scala.collection.mutable.Map[Nothing,Nothing] 为此提出。

于 2012-07-21T16:30:38.470 回答
1

正如sepp2k他在评论中已经提到的,该符号Map指的是 的伴随对象Map,它使您可以访问其单个实例。在模式匹配中,这通常用于识别消息:

scala> case object Foo
defined module Foo

scala> def send[A](a: A) = a match { case Foo => "got a Foo" case Map => "got a Map" }
send: [A](a: A)String

scala> send(Map)
res8: String = got a Map

scala> send(Foo)
res9: String = got a Foo

如果您编写Map(),您将调用applyobject 的方法Map。因为你没有给任何值插入到Map编译器不能推断任何类型,因此它必须使用底部类型-Nothing这是每个类型的子类型。尽管存在差异,但它是唯一一种不会破坏类型系统的推断类型。不Nothing存在以下代码将无法编译:

scala> Map(1 -> 1) ++ Map()
res10: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)

如果您查看其类型签名++如下(来源

def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1]

您会注意到下限类型参数B1 >: B。因为Nothing是所有事物的子类型(B在我们的例子中),编译器可以找到一个B1Int在我们的例子中)并成功地推断出我们的 Map 的类型签名。这个下界是必需的,因为B它是协变的(source),

trait MapLike[A, +B, ...] ...

这意味着我们不允许将其作为方法参数传递(因为方法参数处于逆变位置)。如果方法参数不在逆变位置,则类型系统将不再保留Liskov 的替换原则。因此,必须找到编译新类型(这里称为B1)的代码。

正如Didier Dupont已经指出的那样,Scaladoc 2.9 中存在一些错误,这些错误在 2.10 中得到解决。不仅会显示一些遗漏的方法,还可以显示隐式转换添加的方法(例如Array确实显示了 2.10 中的很多方法,而 2.9 中没有显示)。

于 2012-07-21T16:31:56.507 回答