我试图了解隐含参数的来源。以下是泛型类型约束隐式解析的简单演示:
class ImplicitTypeConstraint[+T](val t : T) {
def doSome1(implicit ev: T <:< Int) = println("Int value = " + ev(t))
def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t))
def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t))
}
现在我尝试了这个
val itc = new ImplicitTypeConstraint(10)
itc.doSome1 //compiles fine
itc.doSome1() //compile error, Cannot resolve reference doSome1 with such signature
itc.doSome2 //compile error, not enough arguments for method doSome2
itc.doSome2() //compile error, Cannot resolve reference doSome2 with such signature
itc.doSome3 //compile error, Cannot resolve reference doSome3 with such signature
itc.doSome3() //compiles fine
问题是,doSome1
和doSome2
的签名之间有什么区别?我来自Java,我想,foo()
将调用一个没有 显式 参数的函数,但它似乎找到一个带有一个参数的函数类型为Unit
。
UPD :在我明确构建项目之前,Itellij没有显示错误。 doSome2()
和doSome2
都拒绝编译。
答案 0 :(得分:2)
f()
调用一个带有空参数列表的方法(可能在此列表后面带有隐式参数)。 doSome1
和doSome2
都没有空参数列表,因此itc.doSome1()
和itc.doSome2()
无法编译。 itc.doSome
编译,因为它调用没有参数列表的函数,并插入隐式参数。 itc.doSome2
无法编译,因为范围内没有implicit Unit
。
在itc.doSome3()
中,()
是类型Unit
的值,而不是方法调用括号。所以它实际上是itc.doSome3(())
。编译器应该发出警告:
Warning:(15, 13) Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want.
signature: ImplicitTypeConstraint.doSome3(u: Unit)(implicit ev: <:<[T,Int]): Unit
given arguments: <none>
after adaptation: ImplicitTypeConstraint.doSome3((): Unit)
itc.doSome3();//
^
答案 1 :(得分:1)
我认为重点是,需要在隐式范围内将{strong>类型视为Int
。你可以自己提供
implicit val intView = implicitly[Int <:< Int]
val itc = new ImplicitTypeConstraint(10)
itc.doSome1
然后您可以按如下方式定义doSome1
:
class ImplicitTypeConstraint[+T](val t : T) {
def doSome1()(implicit ev: T <:< Int) = println("Int value = " + ev(t))
def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t))
def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t))
}
然后两个:
itc.doSome1 //compiles fine
itc.doSome1() // compiles fine too
但要致电doSome2
itc.doSome2() //compiles fine
itc.doSome2(intView, println) // implicit won't work here
致电doSome3
。这是在方法中使用含义的通常/正确方法。你最好curry就是这样。
itc.doSome3(println) // compiles fine