使用通配符类型交换Scala中两个数组的元素

时间:2013-03-30 20:49:00

标签: arrays scala generics inheritance

我想做以下事情:

class A[T] (_arr: Array[T]) { var arr = _arr }
class C {
  def foo[T <: A[_]](a: Array[T]){
    var ele1 = a(0)
    var ele2 = a(1)
    for(i <- 0 until ele1.arr.length) {
      val temp = ele1.arr(i)
      ele1.arr(i) = ele2.arr(i)
      ele2.arr(i) = temp
    }
  }
}

但是我得到以下编译器错误:

<console>:15: error: type mismatch;
 found   : temp.type (with underlying type Any)
 required: _$1
             ele2.arr(i) = temp
                           ^

我不确定为什么     ele1.arr(i)= ele2.arr(i) 会工作和     ele2.arr(i)= temp 不会。

编辑:根据雷克斯的建议,我将其更改为以下内容:

class A[T] (_arr: Array[T]) { var arr = _arr }
class C {
  def foo[T, B <: A[T]](b: Array[B]){
    var ele1 = b(0)
    var ele2 = b(1)
    for(i <- 0 until ele1.arr.length) {
      val temp = ele1.arr(i)
      ele1.arr(i) = ele2.arr(i)
      ele2.arr(i) = temp
    }
  }
}

现在编译好了。但是当我做一个测试用例时,如下:

object Test extends App {
  var p = Array.ofDim[A[Int]](2)
  var g1 = new A[Int](Array(1, 2, 3, 4, 5))
  var g2 = new A[Int](Array(6, 7, 8, 9, 10))
  p(0) = g1
  p(1) = g2

  (new C).foo(p)
  p.foreach{ x => println(x.arr.deep.mkString(",")) }
}

我收到以下编译错误:

src/Test.scala:22: error: inferred type arguments [A[Int],Nothing] do not conform to method foo's type parameter bounds [B <: A[T],T]
  (new C).foo(p)
          ^
src/Test.scala:22: error: type mismatch;
 found   : Array[A[Int]]
 required: Array[B]
  (new C).foo(p)
              ^
two errors found

我知道我可以做(新C).fooInt,A [Int],但我真的想让编译器推断它。否则它会破坏我正在做的很多事情的目的。

1 个答案:

答案 0 :(得分:4)

我不明白为什么你在这里使用通配符而不是参数化元素类型。你使编译器变得盲目,并使它更难以确保你做了一些合理的事情。特别是,它意识到由于数组是不变类型的,ele1.arr(i)ele2.arr(i)是相同的类型,因此可以分配。但是当你分配给temp时,它意识到它不知道那个类型实际上是什么,所以它推断出Any,然后当然不能回到数组中,因为它不是实际上 Any;它只是失去了它应该是什么的轨迹。

class C {
  def foo[T, B <: A[T]](b: Array[B]){
    var ele1 = b(0)
    var ele2 = b(1)
    for(i <- 0 until ele1.arr.length) {
      val temp = ele1.arr(i)
      ele1.arr(i) = ele2.arr(i)
      ele2.arr(i) = temp
    }
  }
}

允许编译器一直知道这些类型,这样可以让它更快乐,更安全。