Scala隐式方法参数消除歧义
scala implicit method argument eliminate ambiguity
我不太明白下面的代码:
object M {
implicit object AMarker
implicit object BMarker
def m(ints: Seq[Int])(implicit i: AMarker.type ): Unit = {
println(s"int seq $ints");
}
def m(strs: Seq[String])(implicit s: BMarker.type ): Unit = {
println(s"string seq $strs")
}
}
import M._
m(Seq(1, 2, 3))
m(Seq("a", "b", "c"))
如果不是这两个标记,它不会编译,因为两个 m
方法在类型擦除后具有相同的签名。
但是,我不明白什么是将 AMarker
链接到 Seq[Int]
,以及将 BMarker
链接到 Seq[String]
的 "magic"。
更具体地说,当我调用 m(Seq("a", "b"))
时,编译器如何知道它应该使用隐式 BMarker
,并调用第二个 m
? Seq
不是已经被类型删除了吗?
直接回答你的问题,不,类型擦除还没有发生。隐式搜索必须在完全了解类型的情况下进行。要查看这些方法如何查看 运行 时间,您可以 运行 javap
查看已编译的 类:
scala> :javap M -s
Compiled from "<console>"
public class M$ {
public static final M$ MODULE$;
Signature: LM$;
public static {};
Signature: ()V
public void m(scala.collection.Seq<java.lang.Object>, M$AMarker$);
Signature: (Lscala/collection/Seq;LM$AMarker$;)V
public void m(scala.collection.Seq<java.lang.String>, M$BMarker$);
Signature: (Lscala/collection/Seq;LM$BMarker$;)V
public M$();
Signature: ()V
}
所以基本上编译器已经制作了明确的 运行time 方法。它在编译时查找确切的方法,本质上是使用隐式对象来消除歧义。
很酷的技巧顺便说一句!没见过这么直接用的
我不太明白下面的代码:
object M {
implicit object AMarker
implicit object BMarker
def m(ints: Seq[Int])(implicit i: AMarker.type ): Unit = {
println(s"int seq $ints");
}
def m(strs: Seq[String])(implicit s: BMarker.type ): Unit = {
println(s"string seq $strs")
}
}
import M._
m(Seq(1, 2, 3))
m(Seq("a", "b", "c"))
如果不是这两个标记,它不会编译,因为两个 m
方法在类型擦除后具有相同的签名。
但是,我不明白什么是将 AMarker
链接到 Seq[Int]
,以及将 BMarker
链接到 Seq[String]
的 "magic"。
更具体地说,当我调用 m(Seq("a", "b"))
时,编译器如何知道它应该使用隐式 BMarker
,并调用第二个 m
? Seq
不是已经被类型删除了吗?
直接回答你的问题,不,类型擦除还没有发生。隐式搜索必须在完全了解类型的情况下进行。要查看这些方法如何查看 运行 时间,您可以 运行 javap
查看已编译的 类:
scala> :javap M -s
Compiled from "<console>"
public class M$ {
public static final M$ MODULE$;
Signature: LM$;
public static {};
Signature: ()V
public void m(scala.collection.Seq<java.lang.Object>, M$AMarker$);
Signature: (Lscala/collection/Seq;LM$AMarker$;)V
public void m(scala.collection.Seq<java.lang.String>, M$BMarker$);
Signature: (Lscala/collection/Seq;LM$BMarker$;)V
public M$();
Signature: ()V
}
所以基本上编译器已经制作了明确的 运行time 方法。它在编译时查找确切的方法,本质上是使用隐式对象来消除歧义。
很酷的技巧顺便说一句!没见过这么直接用的