2014-02-24 49 views
1

(T,T)*在擦除後解析爲Seq[(T,T)],但如何將(T,T)*本身表示爲類型?將T *表示爲具體類型

我想問的原因是有我使用的API定義了:

def foo(bar: (String,String)*) = ... 

但是當我嘗試在Seq[(String,String)]傳遞失敗。

我的拉動請求添加在:

def foo(bar: Seq[(String,String)]) = ... 

炸燬由於2種方法具有擦除之後相同的類型。

星形投影是否可以表示爲具體類型?

val s:Seq[(String, String)] = Seq(("a", "b"), ("c", "d"), ...) 
foo(s:_*) 

所以,你不應該需要兩個簽名:

+0

沒有'T *'類型(對於任何'T')。它僅僅作爲一種將多個實際參數傳遞給具有某種「Seq [T]」的單一形式參數的模式。 –

回答

4

如果你:_*這樣跟隨它可以通過Seq

+1

+1謝謝!我不希望在每個調用站點使用:_ *,這有點繁瑣/神祕,但是比我隱藏的ListMap hack更好地滿足API方法的重載之一。 – virtualeyes

+0

我同意。我希望有一種方法可以使這兩種情況下的簽名工作乾淨利落,但我不知道其中的一種。也許別人會來,並告訴我們一種方法,使其工作。 – joescii

+0

這有點奇怪,但考慮到其他形式的魔法有多混淆,如自動拼接,如果它可以無縫工作以隱藏vargs而不令人驚訝,那將是一件令人驚訝的事情。 –

3

消除歧義擦除簽名:

scala> class X { def f(is: Int*) = is.sum } 
defined class X 

scala> class Y extends X { def f(is: Seq[Int])(implicit d: DummyImplicit): Int = f(is: _*) } 
defined class Y 

scala> new Y().f(1 to 10) 
res3: Int = 55 

或者這是更好的,在收集簽名總是這個樣子爲「兩個或更多」:

scala> class X { 
    | def f(i: Int): Int = i 
    | def f(is: Seq[Int]): Int = is.sum 
    | def f(i: Int, j: Int, rest: Int *): Int = i + j + rest.sum 
    | } 
defined class X 

scala> new X().f(3) 
res9: Int = 3 

scala> new X().f(3,4) 
res10: Int = 7 

scala> new X().f(3,4,5) 
res11: Int = 12 

scala> new X().f(1 to 10) 
res12: Int = 55 

您無法參考轉換爲重複的參數類型,就像你不能引用一個名稱參數類型一樣。所以你不能轉換成它。但是,您可以反思檢測到它,按名稱:

scala> import reflect.runtime.universe._ 
import reflect.runtime.universe._ 

scala> typeOf[X].member(TermName("f")).asMethod.paramss.flatten.head.asTerm.typeSignature.typeSymbol.name 
warning: there were 1 deprecation warning(s); re-run with -deprecation for details 
res4: reflect.runtime.universe.Symbol#NameType = <repeated> 

有內部API,definitions.isRepeated(sym),如果你想投給它。

+0

+1徹底解釋,會很高興給這兩個答案點頭。現在我明白爲什麼API定義(T,T)*而不是Seq [(T,T)],重複參數。 – virtualeyes

相關問題