加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 我如何区分def foo [A](xs:A *)和def foo [A,B](xs:(

发布时间:2020-12-16 09:22:53 所属栏目:安全 来源:网络整理
导读:我知道类型擦除使得它们在运行时看起来是平等的,以便于: 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 definitio
我知道类型擦除使得它们在运行时看起来是平等的,以便于:

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

多个参数列表连接在字节码中的单个参数列表中,因此避免了双重定义问题.

请考虑这个机会来了解擦除,上下文边界和隐含搜索,而不是作为在真实代码中应用的模式!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读