Scala新手指南:我很困惑
object myApp extends App {
println("Echo" + (args mkString " "))
}
"
\"args\"是一个Array[String]类型,但在scaladoc中,Array没有这样的方法。mkString是一个Vector的方法,但我没有看到两者之间的任何继承链接。那么为什么我们可以在args上使用mkString方法?
"我不是scala专家(离得很远!),但我认为答案是隐式转换(请参见scala.Predef
)和WrappedArray.scala。
特别地,Predef有以下隐式转换:
implicit def genericWrapArray [T] (xs: Array[T]): WrappedArray[T]
而 WrappedArray 有一个 mkString 方法。当 Scala 在数组上找不到 mkString 方法时,它会寻找一个隐式转换到具有该方法的类型。
http://www.scala-lang.org/api/current/scala/Predef$.html
http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html
$ scalac -d classes -Xprint:typer A.scala
[[syntax trees at end of typer]]// Scala source: A.scala
package <empty> {
final object myApp extends java.lang.Object with App with ScalaObject {
def this(): object myApp = {
myApp.super.this();
()
};
scala.this.Predef.println("Echo ".+(scala.this.Predef.refArrayOps[String](myApp.this.args).mkString(" ")))
}
}
Predef.refArrayOps
实际上是使用的隐式转换。它将数组转换为ArrayOps[String]
,该类型确实具有mkString
方法。Array
的scaladoc无法告诉您哪个隐式转换适用。它可能是任何东西。实际上,这完全基于不存在该方法的事实。只有编译器才能根据代码知道它找到了哪个隐式。object myApp extends App {
implicit def myImplicit(arr:Array[String]) = new {
def mkString(s:String) = arr.length + s
}
println("Echo " + (args mkString(" ")))
}
这将产生以下效果:
$ scala -cp classes myApp a b c
Echo 3
显然,scaladoc无法展示这一点。请注意,Eclipse Scala插件可以通过按下F3(你会进入TraversableOnce
)来将你带到mkString
的实现。
但是Scaladoc至少可以说Predef(因为它总是在范围内)有一个从Array进行隐式转换的特殊功能。那将会很有用。