[一个非常简单的用例,假设我有一个接受2个参数的类Foo
,1是普通参数,而1是隐式的。
class Foo(val msg: String, implicit val n: Int) {
def multiplier = msg * n
}
implicit val num: Int = 4
val foo = new Foo("yo")
println(foo.msg)
我知道如果我将隐式参数移动到另一个列表(即咖喱class Foo(val msg: String)(implicit val n: Int)
),它将起作用。但是可以说由于某种原因我不想这样做。
有人可以解释为什么当前的实现版本不起作用吗?
语言规范是以这种方式编写的。您必须在单独的参数列表中进行定义。语言规范根本不是在谈论隐式参数,而只是在谈论隐式参数列表:
可能可以检查邮件列表档案或其他地方是否有某些原因。<方法的
(implicit p1,…,pn)
将参数p1
,…,pn
标记为隐式。一个方法或构造函数只能有一个隐式参数列表,并且它必须是给定的最后一个参数列表。
class Foo(val msg: String, implicit val n: Int)
我们实际上不是在声明类constructor parameter
n
是隐式的,相反,我们是在声明相应的类member是隐式的。因为我们已经声明n
为val
,所以它扩展为类似class Foo { ... implicit def n(): Int = n; private[this] val n: Int = _; def <init>(msg: String, n: Int) = { // note how msg and n are *NOT* implicit ... } }
并且将成员声明为隐式是完全合法的。另一方面,如果我们删除val
声明,从而不声明成员,我们将看到它没有编译
class Foo(val msg: String, implicit n: Int) // Error: 'val' expected but identifier found ^
类似于在方法定义中如何非法
def foo(msg: String, implicit n: Int) = ??? // Error
作为补充,以下Scala 2要求一种方法或构造函数只能具有一个隐式参数列表,并且它必须是给定的最后一个参数列表。已由Scala 3 Multiple Given Clauses放宽
在定义中可以有几个个给定的参数子句,给定的参数子句可以与普通子句自由混合。示例:
def f(u: Universe)(given ctx: u.Context)(given s: ctx.Symbol, k: ctx.Kind) = ...
其中given
corresponds至implicit
。