【问题标题】:Collection structural type parameter weirdness集合结构类型参数怪异
【发布时间】:2016-08-11 12:56:31
【问题描述】:

这似乎是一件简单的事情,但我无法理解......

这样编译:

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))的集合是正确的类型,但是当两个对象都在集合中时它放弃了吗?我在这里做错了什么?

【问题讨论】:

    标签: scala generics structural-typing


    【解决方案1】:

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

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

    当您将这两个元素都传递给Seq 时,编译器会尝试寻找可以有效推断的通用类型以使代码编译,并且它可以找到的唯一类型是Object,但是@ 987654331@ 据说是 Seq[CanFoo] 类型,所以编译器会大喊大叫。

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

    class B extends A {
      def fooers = Seq[CanFoo](
        CanFoo1,
        CanFoo2
      )
    }
    

    【讨论】:

    • 感谢您的快速和翔实的回答。我想我现在明白了——没有显式类型参数,Collection 类型是从元素中推断出来的,然后——检查这个推断的类型是否符合结构类型。类型推断器在推断 Seq 的类型时,它所知道的事物中不包括声明的结构类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多