我将两个实用程序方法声明为implicit
class MyClass { ... }
object MyClass {
implicit def finish: MyClass[Any,Nothing,Unit] = finish(());
implicit def finish[R](result: R): MyClass[Any,Nothing,R] = ...
}
我收到编译器警告:
参数化的重载隐式方法作为视图边界不可见
这个警告是什么意思?
我将两个实用程序方法声明为implicit
class MyClass { ... }
object MyClass {
implicit def finish: MyClass[Any,Nothing,Unit] = finish(());
implicit def finish[R](result: R): MyClass[Any,Nothing,R] = ...
}
我收到编译器警告:
参数化的重载隐式方法作为视图边界不可见
这个警告是什么意思?
这里的“参数化”实际上应该是“类型参数化”。或者在其他方面,警告说因为您已经定义了一个隐式转换,它既是重载的(还有其他同名的方法)又是泛型的,那么该方法实际上不能用作隐式视图,尽管它可以使用隐式转换一个单纯的值。我将尝试用一个例子来说明差异:
class MyClass
object MyClass {
implicit def finish: MyClass = null
implicit def finish[R](result: R): MyClass = null
}
val a: Int = 123
val b: MyClass = a // Compiles fine: implicit conversion properly applied
def foo[R<%MyClass]( r: R ) {}
foo( 123 ) // Error: No implicit view available from Int => Test.MyClass
在上面的代码片段中,a
(of type Int
) 被隐式转换为MyClass
,因此隐式转换按预期工作。
然而,有趣的部分在于foo
方法。它是用绑定到的视图声明的MyClass
。换句话说,您应该能够传递给foo
任何可隐式转换为MyClass
. 但是在这里它无法编译。这是编译器警告您的这个错误。果然,如果您注释掉finish
(不带类型参数的那个)的第一个重载,或者重命名一个版本以使其不是重载(例如您将其中一个重命名为finish2
),那么编译错误就会消失.
如果您想知道第一种情况(直接隐式转换)和第二种情况(调用具有视图绑定的方法)之间有什么不同,这将允许一个编译良好但不能编译另一个,关键是视图绑定需要传递一个隐式函数值。
确实,
def foo[R<%MyClass]( r: R )
是相同的
def foo[R]( r: R )( implicit conv: R => MyClass)
所以在调用时foo
,编译器不仅要找到合适的隐式转换,还要将隐式转换方法(第二次finish
重载)提升为函数实例,隐式传递给foo
.
我相信这是编译器(出于某种原因)在类型参数化和重载方法的情况下不知道该怎么做的提升。这纯粹是猜测,但我很确定这只是一个实现限制:这非常可行,但它会引入足够多的实现问题,以至于它被认为不够重要(毕竟你可以通过重命名隐式来解决它转换方法)。
附带说明一下,在 scala 2.10 中(默认情况下)不会发出警告(它被认为太吵了,随着 scala 中类型类使用的激增),但真正的问题仍然存在,并且调用foo
仍然无法编译。