【发布时间】:2020-11-03 17:20:31
【问题描述】:
我在玩隐式,但我有一些我不理解的行为。
我定义了一个简单的类及其伴生对象(只是为了对隐式进行快速测试)如下
class SimpleNumber(val numb: Int) {
def sum(n: Int) = numb + n
}
object SimpleNumber {
implicit def stringToInt(s: String) = s.toInt
}
stringToInt 方法应该在我通过传递一个字符串而不是一个 int 来调用 sum 方法的情况下工作,以便它可以转换为一个 int(它只是为了测试目的,所以我不需要检查错误或异常)。
如果我将上述代码粘贴到 repl (:paste) 中,我会收到此警告
警告:应该启用隐式转换方法 stringToInt 通过使隐式值 scala.language.implicitConversions 可见。 这可以通过添加导入子句“import scala.language.implicitConversions”来实现 或通过设置编译器选项 -language:implicitConversions。
所以我转到 VSCode 并粘贴了相同的代码,以查看是否可以通过金属插件获得更多信息,但该警告甚至没有弹出。然后我创建了一个扩展 App trait 的新对象来测试这样的代码
object TestDriver extends App{
val a = new SimpleNumber(4)
println(a.sum("5"))
}
但我收到以下错误
类型不匹配;发现:String("5") required: Int
我尝试按照 repl 的建议导入 implicitConversions,首先在伴随对象中,然后在 TestDriver 对象中,但无济于事。然后我直接在 TestDriver 对象中导入了隐式方法,并且成功了。
import SimpleNumber.stringToInt
object TestDriver extends App{
val a = new SimpleNumber(4)
println(a.sum("5"))
}
为什么import scala.language.implicitConversions 没有像我想象的那样工作?我正在使用 scala 2.13.3
【问题讨论】:
-
那个隐式根本不在你想要的范围内。检查FAQ 当您执行
a.sum("5")时,编译器将尝试在当前词法范围内搜索隐式转换 (顺便说一句,不鼓励),或者在源类型和目标类型 (分别为 Int 和 String) 的伴随对象中,并且它们都没有这样的隐含。但是,您可以在之前使用import SimpleNumber._,以便将转换放入词法范围,但这不是您想要的。 TL;博士;SimpleNumber对象不在范围内。 -
抱歉,我还是不明白为什么
SimpleObject不在范围内,以及如何引入范围 -
我的意思是
SimpleObject的主体不在 Int 到 String 转换的隐式范围内,为什么?因为这就是规范所说的(但原理很简单,隐式范围不能太大,因为编译器会更慢)。您可以通过显式导入将其隐式成员带入范围,就像将任何内容带入范围一样。伴随对象在隐式范围内的规则适用于源类型和目标类型,例如,如果您希望将 SimpleObject 转换为 String 或反之亦然工作过 -
你好像在学习Scala,我不得不说一些与问题无关的东西:远离隐式转换。该男子本人的话:contributors.scala-lang.org/t/…
-
另外,这就是你必须显式导入 scala.language.implicitConversions 的原因。在 Scala 2.13 中,默认情况下已禁用它,因此您仅在确定需要它时才使用它
标签: scala implicit-conversion implicit