为什么我从这段代码中得到Queue [Nothing]而不是Queue [Book]?

时间:2015-09-26 11:39:50

标签: scala type-inference

这是楼梯书中的一个例子(经过一些修改):

object Example {
  class Queue[+T] private (
                          private[this] var leading: List[T],
                          private [this] var trailing: List[T]
                            ) {
    private def mirror: Unit = {
      if(leading.isEmpty) {
        while(!trailing.isEmpty) {
          leading = trailing.head :: leading
          trailing = trailing.tail
        }
      }
    }

    def this() = this(Nil, Nil)

    def head: T = {
      mirror
      leading.head
    }

    def tail: Queue[T] = {
      mirror
      new Queue(leading.tail, trailing)
    }

    def enqueue[U >: T](x: U) = new Queue[U](leading, x :: trailing)

    def enqueue[U >: T](xs: U*) = new Queue[U](leading, xs.reverse.toList ::: trailing)

    def size = leading.size + trailing.size
  }

  object Queue {
    def apply[T, U <: T](xs: U*): Queue[T] = new Queue(xs.toList, Nil)
    def apply[T]: Queue[T] = new Queue[T](Nil, Nil)
  }

  class Publication
  class Book extends Publication
  class Novel extends Book
  class Journal extends Publication
  class Magazine extends Publication

}

object Test {

  import Example._
  {
    val q = new Queue[Int]()
    val q1 = q.enqueue[Int](1, 2, 3)
    q1.head // 1
    val p = Queue(new Book, new Book, new Book) // Queue[Nothing] ?
  }
}

我从此行获得p类型的Queue[Nothing]

    val p = Queue(new Book, new Book, new Book) // Queue[Nothing] ?

我期待Queue[Book]。编译器是如何得出这个结论的,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

类型参数混淆了类型推断,我认为是因为第二个构造函数参数Nil。仅使用一个类型参数T

  object Queue {
    //    def apply[T, U <: T](xs: U*): Queue[T] = new Queue(xs.toList, Nil)
    def apply[T](xs: T*): Queue[T] = new Queue(xs.toList, Nil)

    def apply[T]: Queue[T] = new Queue[T](Nil, Nil)
  }

这就是现在的工作方式:

val b1 = new Book
val b2 = new Magazine
val b3 = new Journal
val p = Queue(b1, b2, b3)  // Example.Queue[Example.Publication]

这正确地将类型推断为Publication