这是楼梯书中的一个例子(经过一些修改):
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]
。编译器是如何得出这个结论的,我该如何解决这个问题?
答案 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
。