我正在读这本书 Scala in Depth ,第5章关于implicits。作者在第102页说明了这一点:
隐式视图使用的隐式作用域与隐式参数相同。但是当编译器正在寻找类型关联时,它会使用它试图从 [我的强调]转换 的类型,而不是它试图转换为的类型。
然而,几页之后,他展示了一个示例,其中包含complexmath.ComplexNumber
类。您导入i
ComplexNumber
,并将其称为*
方法,该方法采用ComplexNumber
参数。
import complexmath.i
i * 1.0
要将1.0转换为ComplexNumber
,会找到一个如此定义的隐式转换:
package object complexmath {
implicit def realToComplex(r: Double) = new ComplexNumber(r, 0)
val i = ComplexNumber(0, 1)
但这与第一个陈述相矛盾,不是吗?它需要找到Double => ComplexNumber
。为什么它会在complexmath
包中查找,这是[{1}}的隐式范围的一部分,而不是ComplexNumber
的隐式范围的一部分?
答案 0 :(得分:2)
规范说明了观点:
隐式范围是T =>之一。角
,即Function[T, pt]
,因此隐式范围包括与T
和pt
相关联的类,转换的来源和目标。
scala> :pa
// Entering paste mode (ctrl-D to finish)
class B
class A
object A { implicit def x(a: A): B = new B }
// Exiting paste mode, now interpreting.
warning: there were 1 feature warning(s); re-run with -feature for details
defined class B
defined class A
defined object A
scala> val b: B = new A
b: B = B@63b41a65
scala> def f(b: B) = 3 ; def g = f(new A)
f: (b: B)Int
g: Int
scala> :pa
// Entering paste mode (ctrl-D to finish)
class A
class B
object B { implicit def x(a: A): B = new B }
// Exiting paste mode, now interpreting.
scala> val b: B = new A
b: B = B@6ba3b481
答案 1 :(得分:1)
我认为你误解了他的文字。
编译器将在所有可用范围中查找隐式转换,直到找到合适的范围。
在您指定的示例中,我们会发现 complexmath 包提供了一个。
然而,合适的定义是'我们感兴趣的是这里。在隐式转换的情况下,编译器将寻找从 * Double *到预期类型 ComplexNumber 的转换。
换句话说,它会检查所有转化来自 * Double *,直到找到可以将 Double 转换为目标类型。
作者Josh并不是说编译器需要在与 Double 对象关联的对象中定义转换。转换可以在任何地方定义。
在这种特殊情况下,转换是在与 ComplexNumber 对象关联的包对象中定义的。这是正常的,是“想要'的ComplexNumber对象”。与 Double 兼容。
由于使用意味着导入 ComplexNumber ,因此导入包' complexmath ',转换将始终在范围内。
答案 2 :(得分:1)
所以这更多是关于编译器已经*知道关于表达式的内容。
您在示例中有:
import complexmath.i
i * 1.0
编译器以此开头:
1)我有i
的类型,它是Complex
2)我在i
上有一个名为*
的方法,它采用Complex
类型的参数
3)你传给我一个Int
,但我需要一个Complex
。让我们看看我是否有隐含的东西给了我。
此示例有效,因为*
方法是在Complex上定义的。
希望有所帮助!
答案 3 :(得分:0)
源或目标都有效:
object Foo {
implicit def bar(b: Bar): Foo = new Foo {}
implicit def foo(f: Foo): Bar = new Bar {}
}
trait Foo
trait Bar
implicitly[Foo => Bar] // ok
implicitly[Bar => Foo] // ok
val b = new Bar {}
val bf: Foo = b // ok
val f = new Foo {}
val fb: Bar = f // ok
所以我觉得这句话错了(?)