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()
的{{1}}时,将调用相应的随播广告对象中的new
方法。但Scala文档没有为可变映射列出apply
方法(仅提供了从地图中检索值的apply
方法)。
为什么上面的代码仍然有效?
答案 0 :(得分:5)
它看起来像是scaladoc中的一个错误。对象apply
中的是 collection.mutable.Map
方法(继承自GenMapFactory
),但它没有出现在Map的文档中。这个问题似乎在the doc for upcomping 2.10中得到修复。
注意:您必须查看对象文档,而不是第一类。 apply
中的方法class
当然适用于现有的地图实例,并从中检索数据。
答案 1 :(得分:3)
scala.collection.immutable.Map()
的伴随对象上有一个apply()方法。它继承自scala.collection.MapFactory
。该方法采用可变数量的对参数,通常用作
Map("foo"->3, "bar"->4, "barangus"->5)
没有任何参数调用它显然也有效,但是比我更聪明的人必须解释为什么类型推理引擎会为它提出scala.collection.mutable.Map[Nothing,Nothing]
。
答案 2 :(得分: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()
,则会调用对象apply
的{{1}}方法。因为您没有给任何值插入Map
,编译器无法推断任何类型,因此它必须使用bottom type - Map
- 这是每种类型的子类型。虽然存在差异,但它是推断哪种类型不会破坏类型系统的唯一可能类型。如果Nothing
不存在,则以下代码将无法编译:
Nothing
如果您查看scala> Map(1 -> 1) ++ Map()
res10: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)
的类型签名,如下所示(source)
++
您会注意到下限类型参数def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1]
。因为B1 >: B
是所有内容的子类型(在我们的例子中是Nothing
),编译器可以找到B
(在我们的例子中是B1
)并成功推断出类型签名为我们的地图。需要此下限是因为Int
是协变的(source),
B
这意味着我们不允许将它作为方法参数传递(因为方法参数处于逆变位置)。如果方法参数不是逆变位置Liskov's substitution principle将不再由类型系统保留。因此,必须找到编译新类型(此处称为trait MapLike[A, +B, ...] ...
)的代码。
正如B1
已经指出的那样,Scaladoc 2.9中存在一些错误,这些错误在2.10中得到解决。不仅会显示一些错过的方法,而且还可以显示通过隐式转换添加的方法(例如,Array会显示2.10中的许多方法,这些方法未在2.9中显示。)