我将两个实用方法声明为implicit
class MyClass { ... }
object MyClass {
implicit def finish: MyClass[Any,Nothing,Unit] = finish(());
implicit def finish[R](result: R): MyClass[Any,Nothing,R] = ...
}
我正在收到编译器警告:
参数化重载的隐式方法不可视为视图边界
这个警告是什么意思?
答案 0 :(得分:4)
这里“参数化”应该是“类型参数化”。 或者在其他方面,警告说因为你已经定义了一个隐式转换,它既是重载(还有其他同名方法)和泛型,那么方法实际上不能用作隐式视图,尽管它可以用于隐式转换纯值。 我将尝试用一个例子来说明差异:
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
(类型为Int
)隐式转换为MyClass
,因此隐式转换按预期工作。
然而,有趣的部分是使用foo
方法。它被声明为绑定到MyClass
的视图。换句话说,您应该能够将foo
任何可隐式转换为MyClass
的值传递给finish
。但是这里无法编译。这是编译器警告您的此错误。
当然,如果你注释掉finish2
的第一个重载(不带类型参数的那个),或者重命名一个版本以使它们不重载(比如你将其中一个重命名为{{1}然后编译错误就消失了。
如果你想知道第一种情况(直接隐式转换)和第二种情况(带有视图绑定的方法调用)之间有什么不同,这将允许一个编译正常而不是另一个,关键点是视图绑定需要传递一个隐式函数值。
确实,
def foo[R<%MyClass]( r: R )
与
相同def foo[R]( r: R )( implicit conv: R => MyClass)
因此,当调用foo
时,编译器不仅需要找到适当的隐式转换,还需要将隐式转换方法(第二个finish
重载)提升为函数实例,并传递它隐含地foo
。
我认为这是促销,编译器(出于某种原因)在类型参数化和重载方法的情况下不知道如何做。 这是纯粹的推测,但我很确定这只是一个实现限制:这非常可行,但它会引入足够的实现问题而不被认为是足够重要的(毕竟你可以通过重命名隐式修复它转换方法)。
作为旁注,scala 2.10中没有发出警告(默认情况下)(它被认为太嘈杂,scala中类型类使用量激增),但真正的问题仍然存在,并调用{{ 1}}仍然无法编译。