在我的 Scala 代码中,我有一些隐式转换,并且我有必要的导入:
import scala.language.implicitConversions
但是,有时在此导入之后完成另一个导入时,我会收到警告,就好像导入根本不存在一样:
警告:(112, 18) 应启用隐式转换方法对 2Dimension 通过使隐式值 scala.language.implicitConversions 可见。
build.sbt:
name := "ImplicitSBT"
version := "1.0"
scalaVersion := "2.11.5"
scalacOptions ++= Seq("-deprecation","-feature")
libraryDependencies += "org.scala-lang.modules" %% "scala-swing" % "1.0.1"
Main.scala:
import scala.language.implicitConversions
import scala.swing.{Action, _}
object Main extends App {
implicit def pair2Dimension(pair: (Int, Int)): Dimension = new Dimension(pair._1, pair._2)
val dim : Dimension = (0,0)
println(dim)
}
为什么会这样?import scala.swing.{Action, _}
如何隐藏导入implicitConversions
?
如中所述
http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html
通配符导入(如您所写)为任何 Swing 隐式定义提供了相当高的优先级,这显然隐藏了您的定义。
既然你正在使用 SBT 进行编译,那么传递以下设置不是更容易吗
scalacOptions ++= Seq(
"-feature",
"-language:implicitConversions"
)
并且不再担心导入scala.language.implicitConversions
的正确位置是什么?
导入 scala.swing 如何。{操作, _} 隐藏隐式转换导入?
你:
import scala.language.implicitConversions
。被包对象中定义的implicitConversions
scala.swing
阴影:
package scala
...
package object swing {
...
implicit lazy val implicitConversions = scala.language.implicitConversions
...
}
由于您在此处使用通配符导入:
import scala.swing.{Action, _}
。 scala.swing.implicitConversions
从scala.swing
导入,最后阴影scala.language.implicitConversions
。
有趣的问题是:如果有两个"功能标志"(在这种情况下implicitConversions
),为什么scalac
无法弄清楚语言功能已启用,一个在同一级别上隐藏另一个。
这可能是一个错误,也是如何实现SIP 18的细节。
无论如何,为了解决这个问题,我可以建议您执行以下操作之一:
不要导入
scala.language.implicitConversions
(因为通配符导入时scala.swing
已经导入
)不要从
scala.swing
进行通配符导入(不要污染您的范围并导入您需要的内容)在
Main
对象级别执行另一个导入(不被另一个导入)implicitConversions
这是隐式查找中的一个错误。
这是更普通代码中的相同结构,其中所需的隐式是执行上下文。
(通配符导入是否来自包对象,或者另一个包是否位于同一编译单元中并不重要。
由于代码是用显式global
编译的,它应该用隐式参数编译。
没有前缀的情况下访问,则隐式可用。
绑定优先级不受源代码顺序的影响。阴影以通常的方式工作;绑定永远不会隐藏更高优先级的绑定。
/*
package object bound2 {
implicit lazy val global = scala.concurrent.ExecutionContext.Implicits.global
}
*/
package bound2 {
object B {
implicit lazy val global: concurrent.ExecutionContextExecutor = scala.concurrent.ExecutionContext.global
}
}
package bound {
// the order of these imports in the same scope should not matter
import scala.concurrent.ExecutionContext.Implicits.global
import bound2.B._
object Test extends App {
val f = concurrent.Future(42) //(global) // explicit arg works
Console println concurrent.Await.result(f, concurrent.duration.Duration.Inf)
}
}
在规范示例 2.0.1 中,添加标记为"OK"的行会编译,您可以验证顺序无关紧要,但它在内部作用域中变得不明确,因为那里的"通配符 y"不会遮盖外部作用域中的"显式 y":
import X.y // `y' bound by explicit import
println("L16: "+y) // `y' refers to `Q.X.y' here
import P.X._
println("OK: "+y) // `y' refers to `Q.X.y' here
locally { val x = "abc" // `x' bound by local definition
import P.X._ // `x' and `y' bound by wildcard import
// println("L19: "+y) // reference to `y' is ambiguous here