【问题标题】:Why does Scala compiler think there is a polymorphic type error?为什么Scala编译器认为存在多态类型错误?
【发布时间】:2015-05-22 02:15:40
【问题描述】:

我的代码很简单:

class MyClass {
  var foo: IndexedSeq[MyClass] = IndexedSeq()
  def bar(newValues: MyClass*) = foo = newValues.toArray
}

该类包含一个变量和一个方法。变量 fooIndexSeqMyClass 对象。它还包含一个方法bar,它将SeqMyClass 对象作为参数。因为Seq[T]不能分配给IndexSeq[T],因为后者是前者的子类,所以我不得不调用toArray

使用此代码,编译器报错如下

polymorphic expression cannot be instantiated to expected type;
 found   : [B >: MyClass]Array[B]
 required: IndexedSeq[MyClass]
  def bar(newValues: MyClass*) = foo = newValues.toArray
                                                 ^

于是我找到了解决办法,就是调用toIndexSeq而不是toArray,编译器就不再报错了。

即使问题对我来说已经消失了,我仍然想知道为什么会出现这样的错误。

【问题讨论】:

标签: scala types polymorphism


【解决方案1】:

如果您查看spec for Array,您会注意到它没有扩展SeqIndexedSeq。事实上,Array 是一个非常简单的类,它只扩展了 SerializableCloneable,因为它基于 Java 的 Array 实现。您可能习惯于将其视为 Seq,因为在 ArrayArrayOps 中提供了隐式转换。

问题是没有从Array[B >: MyClass](这是toArray 返回的内容)到IndexedSeq[MyClass] 的隐式转换。如果显式提供toArray的泛型参数或者使用类型归属,这个问题就解决了,因为有Array[MyClass]Seq[MyClass]的隐式转换:

def bar(newValues: MyClass*) = foo = newValues.toArray[MyClass]
def bar(newValues: MyClass*) = foo = (newValues.toArray : Array[MyClass])

这个更简单的例子可能有助于阐明:

class Foo
Seq(new Foo).toArray : Seq[Foo] //fails
Seq(new Foo).toArray[Foo] : Seq[Foo] //works!
(Seq(new Foo).toList.toArray : Array[Foo]) : Seq[Foo] //also works!

【讨论】:

  • toArray 返回的 Array 是否与 this diagram 中的 Array 不同?
  • 不,我猜那些带有虚线的箭头意味着ArrayString可以隐式转换为IndexedSeq
  • 是 -- 虚线箭头表示Predef 中存在隐式转换,粗线表示实例化特征的方法返回的默认类型。例如,Seq() 返回 List()(即 LinearSeq),IndexedSeq 返回 Vector
猜你喜欢
  • 2018-10-11
  • 2020-06-30
  • 2020-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
相关资源
最近更新 更多