用通配符类型在Scala中交换两个数组的元素 [英] Swapping elements of two Arrays in Scala with wildcard type

查看:599
本文介绍了用通配符类型在Scala中交换两个数组的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

pre $ < console> :15:错误:类型不匹配;
找到:temp.type(带底层类型任何)
必需:_ $ 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)
(i <-0直到ele1.arr.length){
val temp = ele1.arr(i)
ele1.arr(i)= ele2.arr(i)
ele2 .arr(i)= temp
}
}
}

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

  object Test扩展应用程序{
var p = Array.ofDim [A [Int]](2)
var g1 = new A [Int](Array(1,2,3,4,5))
var g2 = new A [Int] (新)C).foo(P)
(0)= g1
p(1)= g2

p.foreach {x => println(x.arr.deep.mkString(,))}
}

我得到以下编译器错误:

$ s $ s $ s $ / $ s $ s $ / $ s $ / $ s $ / $ s $ / Nothing]不符合方法foo的类型参数bounds [B <:A [T],T]
(new C).foo(p)
^
src / Test.scala :22:错误:类型不匹配;
found:Array [A [Int]]
required:Array [B]
(new C).foo(p)
^
找到两个错误

我明白我可以做(新C).fooInt,A [Int],但我真的喜欢让编译器推断它。我不明白你为什么要这样做,因为我不知道你为什么要这样做,在这里重新使用通配符而不是参数化元素类型。你正在盲目地编译器,并且让它更难以确保你正在做一些明智的事情。特别是,它意识到由于数组是不变的类型,所以 ele1.arr(i) ele2.arr(i)是同一类型,因此可以分配。但是,当你分配给 temp 时,它意识到它不知道该类型可能实际是什么,所以它推断任何,然后当然不会回到数组中,因为它实际上不是 Any ;

  class C {
def foo [T,B< ;:对于(i < - 0直到ele1为止,A [T]](b:Array [B]){
var ele1 = b(0)
var ele2 = b(1) arr.length){
val temp = ele1.arr(i)
ele1.arr(i)= ele2.arr(i)
ele2.arr(i)= temp
}
}
}

允许编译器知道所有的类型这样可以让你快乐,而且更安全。


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.

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. 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. 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; 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.

这篇关于用通配符类型在Scala中交换两个数组的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆