简体   繁体   English

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

[英]Swapping elements of two Arrays in Scala with wildcard type

I want to do something like the following: 我想做以下事情:

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
    }
  }
}

But I get the following compiler error: 但是我收到以下编译器错误:

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

I'm not sure why ele1.arr(i) = ele2.arr(i) would work and ele2.arr(i) = temp would not. 我不确定为什么ele1.arr(i)= ele2.arr(i)可以工作,而ele2.arr(i)= temp不能工作。

EDIT: According to Rex's Suggestion, I changed it to the following: 编辑:根据雷克斯的建议,我将其更改为以下内容:

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
    }
  }
}

and now that compiles fine. 现在可以编译了。 But when I do a test case, as follows: 但是当我做一个测试用例时,如下:

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(",")) }
}

I get the following compiler error: 我收到以下编译器错误:

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

I understand that I can do (new C).fooInt, A[Int], but I'd really like to have the compiler infer it. 我知道我可以(新C).fooInt,A [Int],但是我真的很想让编译器来推断它。 Otherwise it kind of defeats the purpose of a lot of what I'm doing. 否则,这会破坏我很多工作的目的。

I don't understand why you're using wildcards here instead of parameterizing the element type. 我不明白为什么您在这里使用通配符而不是参数化元素类型。 You're blinding the compiler and making it harder for it to make sure you are doing something sensible. 您使编译器蒙蔽了视线,并使它变得更难确定您在做明智的事情。 In particular, it realizes that since arrays are invariantly typed, ele1.arr(i) and ele2.arr(i) are the same type and thus can be assigned. 尤其是,它认识到由于数组是不变类型的,因此ele1.arr(i)ele2.arr(i)是同一类型,因此可以分配。 But when you assign to temp , it realizes that it has no idea what that type might actually be, so it infers Any , and then of course that won't fit back into the array because it's not actually Any ; 但是当您分配给temp ,它意识到它不知道该类型实际上可能是什么,因此它会推断Any ,然后当然不会适合该数组,因为它实际上不是Any it's just lost track of what it should be. 它只是失去了应有的状态。

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
    }
  }
}

allows the compiler to know the types all the way through, which keeps it happy, and you safer. 允许编译器完全了解类型,从而使编译器保持快乐并更加安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM