我们不能在单个参数列表中混合隐式和非隐式形式参数,因为implicit修饰符是列表的属性,而不是参数。因此下面的方法定义是非法的
def foo(msg: String, implicit n: Int) = ??? // Error
但是为什么以下是合法的
class Foo(val msg: String, implicit val n: Int) // OK
在这里,在声明类构造函数时,在单个参数子句中混合隐式和非隐式参数似乎是合法的,但是implicit修饰符不适用于形参n,而是修改相应的自动生成的访问器成员。因为我们已经声明n它val扩展为类似
class Foo {
...
implicit def n(): Int = n;
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 ^
类似于在方法定义中它是非法的。因此以下无法编译的原因
implicit val num: Int = 4
new Foo("yo") // error: unspecified value parameter n
是因为形参n实际上不是隐含的。
作为旁注,以下 Scala 2 要求
一个方法或构造函数只能有一个隐式参数列表,并且它必须是给定的最后一个参数列表。
已被 Scala 3 Multiple Given Clauses更改
一个定义中可以有多个给定的参数子句,并且给定的参数子句可以与正常的参数子句自由混合。例子:
def f(u: Universe)(given ctx: u.Context)(given s: ctx.Symbol, k: ctx.Kind) = ...
given 对应于哪里implicit。