为什么此代码无法编译,但在取消注释指示的行时成功编译? (我每晚都使用Scala 2.8)。似乎显式调用string2Wrapper
允许从那一点开始隐式使用它。
class A {
import Implicits.string2Wrapper
def foo() {
//string2Wrapper("A") ==> "B" // <-- uncomment
}
def bar() {
"A" ==> "B"
"B" ==> "C"
"C" ==> "D"
}
object Implicits {
implicit def string2Wrapper(s: String) = new Wrapper(s)
class Wrapper(s: String) {
def ==>(s2: String) {}
}
}
}
编辑:感谢目前为止的答案,其中包含指向Martin Odersky评论的指针,
“没有显式结果类型的隐式转换仅在文本中可见 遵循自己的定义。这样,我们就避免了循环参考错误。“
我仍然有兴趣找出1)“循环引用错误”的危险是什么?,2)为什么显式调用有什么不同?
答案 0 :(得分:20)
明确归因于string2Wrapper的返回类型可以解决问题。
class A {
import Implicits._
def bar() {
"A" ==> "B"
"B" ==> "C"
"C" ==> "D"
}
object Implicits {
implicit def string2Wrapper(s: String): Wrapper = new Wrapper(s)
class Wrapper(s: String) {
def ==>(s2: String) {}
}
}
}
在Implicits
之前定义bar
也有效:
class A {
object Implicits {
implicit def string2Wrapper(s: String) = new Wrapper(s)
class Wrapper(s: String) {
def ==>(s2: String) {}
}
}
import Implicits._
def bar() {
"A" ==> "B"
"B" ==> "C"
"C" ==> "D"
}
}
如果您需要依赖当前范围内的下面定义的隐式转换,请确保注释其返回类型。很确定之前已经出现在邮件列表上,可能是预期的行为而不是错误。但我现在无法找到它。我想foo
中的显式调用会触发bar
返回类型的类型推断,然后在输入bar
的内容时有效。
<强>更新强>
循环参考错误有什么危险?
隐式方法的主体可以调用需要隐式转换的方法。如果这两个都具有推断的返回类型,那么你就陷入了僵局。这不适用于您的示例,但编译器不会尝试检测此。
为什么显式通话会产生影响?
先前的显式调用触发隐式方法的返回类型的类型推断。这是Implicits.isValid
sym.isInitialized ||
sym.sourceFile == null ||
(sym.sourceFile ne context.unit.source.file) ||
hasExplicitResultType(sym) ||
comesBefore(sym, context.owner)
更新2
这个最近的错误看起来很相关:https://lampsvn.epfl.ch/trac/scala/ticket/3373
答案 1 :(得分:12)
如果你以后只是在晚上,你会看到我昨天添加的错误信息。
<console>:11: error: value ==> is not a member of java.lang.String
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
"A" ==> "B"
^
<console>:12: error: value ==> is not a member of java.lang.String
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
"B" ==> "C"
^
<console>:13: error: value ==> is not a member of java.lang.String
Note: implicit method string2Wrapper is not applicable here because it comes after the application point and it lacks an explicit result type
"C" ==> "D"
^
答案 2 :(得分:3)
如果你先放object Implicits
,它就可以了。对于我来说,这在编写多个编译器通道的逻辑中看起来像个错误;它假设在编译string2Wrapper
时不知道bar
就可以逃脱。我的猜测是,如果你使用它,它知道它不能逃脱不知道string2Wrapper究竟是什么,实际编译Implicits
,然后意识到==>
是在String上隐式定义的。
编辑:根据Retronym发布的内容,也许这是一个“功能”而非错误。对我来说似乎仍然很棘手!