在我的Scala代码中,我有一些隐式转换,我有必要的导入存在:
import scala.language.implicitConversions
但是,有时当在此之后再进行另一次导入时,我会收到警告,好像导入根本不存在:
警告:(112,18)应启用隐式转换方法pair2Dimension 通过使隐式值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
导入?
答案 0 :(得分:4)
如何导入scala.swing。{Action,_}隐藏implicitConversions导入?
您:
import scala.language.implicitConversions
...在implicitConversions
包对象中被scala.swing
defined遮蔽:
package scala
...
package object swing {
...
implicit lazy val implicitConversions = scala.language.implicitConversions
...
}
由于您在此处使用通配符导入:
import scala.swing.{Action, _}
... scala.swing.implicitConversions
从scala.swing
导入,最后导致阴影scala.language.implicitConversions
。
有趣的问题是:如果有两个“功能标志”(在这种情况下为scalac
),implicitConversions
无法确定语言功能是否已启用,为什么scala.language.implicitConversions
无法确定是否启用了语言功能。
这可能是一个错误以及SIP 18如何实现的具体细节。
无论如何,要解决此问题,我建议您执行以下操作之一:
不导入scala.swing
(因为在通配符导入时已导入scala.swing
)
不要从implicitConversions
进行通配符导入(不要污染您的范围并导入您需要的内容)
在Main
对象级别{{1}}进行另一次导入(不会被另一个导入)
答案 1 :(得分:4)
如
中所述http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html
通配符导入(正如您所写)给予任何Swing隐式定义一个相当高的优先级,并且显然隐藏了你的。
由于您正在使用SBT进行编译,因此传递以下设置并不容易
scalacOptions ++= Seq(
"-feature",
"-language:implicitConversions"
)
并且不再担心什么是正确的导入地点scala.language.implicitConversions
?
答案 2 :(得分:1)
这是隐式查找中的错误。
这是更常规代码中的相同结构,其中所需的隐含是执行上下文。
(通配符导入是来自包对象,还是其他包是否在同一个编译单元中。)
由于代码使用显式global
进行编译,因此应使用隐式arg进行编译。
隐式可用,如果它可以是accessed without a prefix。
binding precedence不受源代码顺序的影响。阴影以通常的方式工作;绑定永远不会影响更高优先级的绑定。
/*
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