集合结构类型参数怪异

时间:2016-08-11 12:56:31

标签: scala generics structural-typing

这似乎很简单,但我无法理解......

编译:

object CanFoo1 {
  def foo(): Unit = {
    println("Yup, I can foo alright")
  }
}

object CanFoo2 {
  def foo(): Unit = {
    println("And I can foo with the best")
  }
}

trait A {
  type CanFoo = { def foo(): Unit }
  def fooers: Seq[CanFoo]
}

class B extends A {
  def fooers = Seq(
    // CanFoo1, // <- won't compile when this is uncommented
    CanFoo2
  )
}

但取消注释// CanFoo1,行会给出:

error: type mismatch;
found   : Seq[Object]
required: Seq[B.this.CanFoo]
   (which expands to)  Seq[AnyRef{def foo(): Unit}]
def fooers = Seq(
              ^
one error found

所以看起来编译器理解只包含一个元素Seq(CanFoo2)(或Seq(CanFoo1))的集合是正确的类型,但当两个对象都在集合中时它会放弃?我在这做错了什么?

1 个答案:

答案 0 :(得分:2)

  

所以看起来编译器理解包含的集合   只有一个元素Seq(CanFoo2)(或Seq(CanFoo1))是正确的   类型,但当两个对象都在集合中时,它会放弃吗?是什么   我在这里做错了吗?

当您将CanFoo1CanFoo2传递给Seq时,序列被推断为分别为CanFoo1.typeCanFoo2.type,而不是推断为CanFoo类型。

当您将两个元素都传递给Seq时,编译器会尝试查找一个可以有效推断的代码编译的公共类型,它可以找到的唯一类型是{{1} },但Object被称为类型fooers,因此编译器会大喊。

您可以通过显式编写集合的类型来帮助编译器:

Seq[CanFoo]