2016-09-23 76 views
3

我不太明白下面的代碼:Scala的隱式方法的參數不確定性消除

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方法具有類型後,相同的簽名擦除。

但是,我不明白什麼是鏈接AMarkerSeq[Int],BMarkerSeq[String]的「魔術」。

更具體地說,當我打電話給m(Seq("a", "b"))時,編譯器如何知道它應該使用隱含的BMarker,並調用第二個mSeq已經被刪除了嗎?

+3

由於Seq [A]的類型信息在編譯時可用於調用正確的方法,但該信息在運行時不可用 – Falmarri

+2

不是您的問題的答案,而是一個有趣的觀察:您還可以消除不明確性通過創建一個'm()'函數並將另一個作爲方法。沒有暗示或標記需要。 – jwvh

回答

0

要直接回答您的問題,不,類型刪除尚未發生。隱式搜索必須在充分了解類型的情況下才能發生。要了解這些方法如何看待在運行時,可以運行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 
} 

所以基本上編譯器取得了明確的運行方式。它在編譯期間查找確切的方法,並基本上使用隱式對象來消除歧義。

酷招BTW!我還沒有看到它以前用過這種方式。