如果我尝试为基本类型定义隐式转换,那么它似乎不起作用。 E.g:
implicit def globalIntToString(a: Int) : String = { a.toString() + "globalhi" }
1.toInt + "hi"
上面的结果仍然只是“1hi”。
然而,似乎如果我参数化一个类或一个def然后传入隐式参数化的情况,那么它似乎工作。有谁知道原因是什么?例如。这是否与pretives的装箱/拆箱有关(例如,参数化的原语被装箱)?隐式只适用于引用类型而不是基本类型吗?
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])
答案 0 :(得分:4)
这里有一些微妙的事情。 @yan已经解释了核心问题 - 我将尝试添加一些更具体的信息。
如上所述,1.toInt + "hi"
永远不会使用任何隐式转换,因为Scala Int
类实际上有一个方法+
,它采用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语言规范的适当引用来确认它。 / p>
正如您所看到的,定义此类转换可能会导致许多奇怪的行为。我肯定会说,向String
引入隐式转换是在寻找麻烦。
答案 1 :(得分:2)
这是因为Scala在Int类型上定义了一个+
运算符,它接受一个String并且不需要解析隐式转换。此外,转换为String
通常是个坏主意,因为您通常会使用自定义的一次性类型来定义您尝试添加的方法。