【问题标题】:scala implicit method argument eliminate ambiguityscala隐式方法参数消除歧义
【发布时间】:2016-09-26 11:47:22
【问题描述】:

我不太明白下面的代码:

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] 的“魔法”是什么。

更具体地说,当我调用m(Seq("a", "b")) 时,编译器如何知道它应该使用隐式BMarker,并调用第二个mSeq 不是已经被删除了吗?

【问题讨论】:

  • 因为 Seq[A] 的类型信息在编译时可用以调用正确的方法,但该信息在运行时不可用
  • 不是您问题的答案,而是一个有趣的观察:您还可以通过将一个 m() 设为函数并将另一个作为方法来消除歧义。不需要隐含或标记。

标签: scala implicit


【解决方案1】:

直接回答你的问题,不,类型擦除还没有发生。隐式搜索必须在完全了解类型的情况下进行。要查看这些方法在运行时的样子,您可以运行 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
}

所以基本上编译器已经制作了明确的运行时方法。它在编译时查找确切的方法,并且本质上使用隐式对象来消除歧义。

很酷的把戏顺便说一句!以前没见过直接这样用的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多