use*_*ser 9 scala implicit scala-3
implicitScala 2 中的关键字和Scala 3 中的given+有什么区别?using是否只是implicit被分成了两个关键字,或者语义也不同,如果是,是如何不同的?
在大多数情况下,它们是相同的。但是,implicit不再用于多个不同的概念。这些文档更详细,但这里是它们的摘要:
声明参数时,using与 相同implicit。但是,当显式传递隐式参数时,您必须使用using:
def foo(using bar: Bar) = ???
foo(using Bar()) //Cannot use just foo(Bar()) as you would in Scala 2
Run Code Online (Sandbox Code Playgroud)
您还可以在 Scala 3 中使用隐式的按名称参数。
Gives 也与隐式 vals/objects/methods 非常相似。
它们的一个好处是它们可以是匿名的,编译器将为它们生成一个名称,看起来就像given_F_X_Y给定的类型是F[X, Y]. 更多详细信息请参见此处。
另一个变化是给定的类型必须显式编写 - 它不能像 Scala 2 中的隐式类型那样推断出来。
不带参数的给定映射到implicit object. given foo: Foo with {...}变得公正implicit object foo extends Foo {...}。
带参数的给定类似于implicit def仅接受更多implicit参数的给定。
given listOrd[T](using ord: Ord[T]): Ord[List[T]] with { ... }
//^^ this maps to this vv
class listOrd[T](implicit ord: Ord[T]) extends Ord[List[T]] { ... }
final implicit def listOrd[T](implicit ord: Ord[T]): listOrd[T] = new listOrd[T]
Run Code Online (Sandbox Code Playgroud)
如果给定的只是一个别名,implicit def则它只是一个引用,否则它就会成为一个implicit lazy val。
val foo: Foo
given Foo = foo
Run Code Online (Sandbox Code Playgroud)
会变成final implicit def given_Foo = foo(注意编译器生成的名称),但是
given foo: Foo = new Foo()
Run Code Online (Sandbox Code Playgroud)
会变成final implicit lazy val foo: Foo = new Foo()因为new Foo()不应该进行不必要的计算。
您现在可以定义给定的实例,而不是使用 an进行从to的implicit def隐式转换。ABConversion[A, B]
您还可以在 Dotty 中仍然使用隐式类,但可以直接定义扩展方法。虽然扩展内部的方法不能采用自己的类型参数,但它们比隐式类更易于使用。
Scala 3 中的另一项更改summon是类似 的方法implicitly,但它可以返回比所请求的类型更具体的类型。