将T *表示为具体类型

时间:2014-02-24 18:16:50

标签: scala types projection concrete

擦除后

(T,T)*解析为Seq[(T,T)],但如何将(T,T)*本身表示为一种类型?

我问的原因是我正在使用的API定义了:

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

但是当我尝试传入Seq[(String,String)]时失败了。

我的拉入请求:

def foo(bar: Seq[(String,String)]) = ...
由于擦除后2种方法具有相同类型,

爆炸。

明星投影是否可以表示为具体类型?

2 个答案:

答案 0 :(得分:4)

如果您使用Seq,请按:_*传递val s:Seq[(String, String)] = Seq( ("a", "b"), ("c", "d"), ... ) foo(s:_*)

{{1}}

所以你不应该同时签名。

答案 1 :(得分: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)