1

以下 Scala 代码可以正常工作:

val str1 = "hallo"
val str2 = "huhu"
val zipped: IndexedSeq[(Char, Char)] = str1.zip(str2)

但是,如果我导入隐式方法

implicit def stringToNode(str: String): xml.Node = new xml.Text(str)

然后 Scala (2.10) 编译器显示错误:value zip is not a member of String

似乎存在以stringToNode某种方式阻止了str1和的隐式str2转换WrappedString。为什么?有没有办法修改stringToNode这样的方法,zip但当stringToNode我调用一个需要带Node参数的函数时仍然使用String

4

2 回答 2

6

你在这里有模棱两可的暗示。StringOps 和 xml.Node 都有 zip 方法,因此隐式转换不明确,无法解析。我不知道为什么它没有给出更好的错误信息。

以下是一些备份它的链接: http ://www.scala-lang.org/api/current/index.html#scala.collection.immutable.StringOps 和 http://www.scala-lang.org/api /current/index.html#scala.xml.Node

编辑:它是 StringOps,而不是 WrappedString,更改了链接 :) 看看 Predef:http ://www.scala-lang.org/api/current/index.html#scala.Predef $ 查看 Scala 中的预定义隐式.

在这种情况下,我会避免使用隐式。您需要 2 个不同的隐式转换,它们都提供同名的方法 ( zip)。我不认为这是可能的。此外,如果您导入 xml.Text,您可以使用Text(str)对任何人都足够简洁的转换。如果您必须将此隐式转换为 xml.Node,我会将隐式 def 打包到一个对象中,然后仅将其导入您需要它以使您的代码可读的地方,并可能避免在您还需要的地方发生冲突拉链字符串。但基本上,我会非常避免使用隐式来进行方便的转换。

于 2013-03-05T19:25:22.633 回答
3

就像@Felix 写的那样,定义类似数据类型之间的隐式转换通常是一个坏主意,就像您使用的那样。这样做会削弱类型系统,导致像您遇到的模棱两可,并可能产生非常不清楚(“魔术”)的代码,很难分析和调试。

Scala 中的隐式转换主要用于定义轻量级、短寿命的包装器,以丰富包装类型的 API。String转换成的隐式转换WrappedString属于该类别。

Twitter 的Effective Scala有一个关于这个问题的部分。

于 2013-03-05T19:42:05.320 回答