0

如果我尝试为原始类型定义隐式转换,那么它似乎不起作用。例如:

implicit def globalIntToString(a: Int) : String = { a.toString() + "globalhi" }
1.toInt + "hi"

上面仍然会简单地返回“1hi”作为结果。

但是,似乎如果我参数化一个类或一个 def,然后为参数化的情况传递隐式,那么它似乎可以工作。有谁知道是什么原因?例如,这是否与图元的装箱/拆箱有关(例如,参数化的图元被装箱)?隐式是否仅适用于引用类型而不适用于原始类型?

class typeConv[T] { implicit def tToStr(a: T) : String = { a.toString() + "hi" } }
class t[K](a: K)(tc : typeConv[K]) { import tc._; println(a + "cool"); println(1.toInt + "cool" ) }
new t(1)(new typeConv[Int])
4

2 回答 2

4

这里发生了一些微妙的事情。@yan 已经解释了核心问题 - 我将尝试添加一些更具体的信息。

如前所述,1.toInt + "hi"永远不会使用任何隐式转换,因为 ScalaInt类实际上有一个+String参数的方法。只有在原始类型中找不到匹配的成员时,编译器才会查找隐式视图。

t在你的课堂上发生了一些更复杂的事情。Scalac 将寻找从泛型类型K到具有带参数的+方法的任何类型的隐式转换。String这种转换将有两个候选者:你自己的tc.tToStr和 Scala 内置的scala.Predef.any2stringadd

通常,any2stringadd将使用,但在您的示例中,使用您自己的转换。为什么它优先于any2stringadd

在隐式搜索期间,tc.tToStr被视为类型的函数K => String,而any2stringadd被视为类型的函数Any => StringAdd。我的猜测是K => String编译器将其视为比更具体的转换Any => StringAdd,但有人必须通过正确引用 Scala 语言规范来确认它。

如您所见,定义此类转换可能会导致您出现很多奇怪的行为。我肯定会说,将隐式转换引入 aString是自找麻烦。

于 2013-09-12T22:28:26.630 回答
2

发生这种情况是因为 Scala+在 Int 类型上定义了一个运算符,该运算符采用 String 并且不需要解析隐式转换。此外,转换String为通常不是一个好主意,因为您通常有一个自定义的一次性类型来定义您尝试添加的方法。

于 2013-09-12T22:18:04.690 回答