scala – 我如何区分def foo [A](xs:A *)和def foo [A,B](xs:(
我知道类型擦除使得它们在运行时看起来是平等的,以便于:
class Bar { def foo[A](xs: A*) { xs.foreach(println) } def foo[A,B](xs: (A,B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) } } 给出以下编译器错误: <console>:7: error: double definition: method foo:[A,B)*)Unit and method foo:[A](xs: A*)Unit at line 6 have same type after erasure: (xs: Seq)Unit def foo[A,B)*) { xs.foreach(x => println(x._1 + " - " + x._2) ) } ^ 但是有没有一个简单的方法来写: bar.foo(1,2,3) bar.foo(1 -> 2,3 -> 4) 并且这些调用不同的重载版本的foo,而不必明确地命名它们: bar.fooInts(1,3) bar.fooPairs(1 -> 2,3 -> 4) 解决方法
你可以在一个相当圆的方式. Foo是一个类型的类,编译器会隐含地传递类型类的实例,与(推断)类型参数A兼容.
trait Foo[X] { def apply(xs: Seq[X]): Unit } object Foo { implicit def FooAny[A]: Foo[A] = new Foo[A] { def apply(xs: Seq[A]) = println("apply(xs: Seq[A])") } implicit def FooTuple2[A,B]: Foo[(A,B)] = new Foo[(A,B)] { def apply(xs: Seq[(A,B)]) = println("apply(xs: Seq[(A,B)])") } def apply[A](xs: A*)(implicit f: Foo[A]) = f(xs) } Foo(1,3) // apply(xs: Seq[A]) Foo(1 -> 2,2 -> 3) // apply(xs: Seq[(A,B)]) 在第二次调用中,FooAny和FooTuple2都可以传递,但编译器根据静态方法重载的规则选择FooTuple2. FooTuple2被认为更具体的是FooAny.如果两个候选人被认为是彼此具体的,则会引起歧义性错误.您也可以通过将一个放在超类中,如在scala.LowPriorityImplicits中所做的那样. UPDATE 解除DummyImplicit的想法,以及scala-user上的后续线程: trait __[+_] object __ { implicit object __ extends __[Any] } object overload { def foo(a: Seq[Boolean]) = 0 def foo[_: __](a: Seq[Int]) = 1 def foo[_: __ : __](a: Seq[String]) = 2 } import overload._ foo(Seq(true)) foo(Seq(1)) foo(Seq("s")) 这在其未命名的类型参数_中声明了一个类型参数化的特征__,协方差.它的伴随对象__包含__ [Any]的隐式实例,稍后我们将需要. foo的第二和第三个重载包括一个虚拟类型参数,再次未命名.这将被推断为任何.此类型参数具有一个或多个上下文边界,它们被排除为另外的隐式参数,例如: def foo[A](a: Seq[Int])(implicit ev$1: __[A]) = 1 多个参数列表连接在字节码中的单个参数列表中,因此避免了双重定义问题. 请考虑这个机会来了解擦除,上下文边界和隐含搜索,而不是作为在真实代码中应用的模式! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |