单例对象的类参数(泛型)

时间:2013-04-14 16:20:17

标签: scala

his course on Coursera中,Martin Odesrky教授在关于多态性和参数化类的讲座中使用链表作为例子:

package week4

trait List[T] {
  def isEmpty: Boolean
  def head: T
  def tail: List[T]
}
class Cons[T](val head: T, val tail: List[T]) extends List[T] {
  def isEmpty = false
}
class Nil[T] extends List[T] {
  def isEmpty = true
  def head = throw new NoSuchElementException("Nil.head")
  def tail = throw new NoSuchElementException("Nil.tail")
}
object Main extends App {
  def main(args: Array[String]) {
    val lst = new Cons("A", new Cons("B", new Cons("C", new Nil())))
  }
}

令我困扰的是最后一行new Nil()中Nil类的实例化。

如何将Nil定义为object而不是Scala类,并使其符合参数化类型List [T]?

我想在下面的代码行中引用Nil对象(没有实例化),并使其具有正确的类型

new Cons("A", new Cons("B", new Cons("C", Nil)))

3 个答案:

答案 0 :(得分:3)

在实际的Scala库(List.scala)中,这是如何完成的,

case object Nil extends List[Nothing] { ...

可能在课堂上他想避免引入Nothingtype at the bottom of Scala's type lattice

答案 1 :(得分:3)

鉴于列表的trait List[T]定义,您无法做到。该定义意味着每个Nil都需要一个不同的T,因为对于每个T1T2,不相同,List[T1]与{{1}不兼容}}。由于List[T2]必须“成为”Nil,因此您选择的任何List[Tx]都将与所有其他Tx不兼容。

要解决这个问题,你需要协方差,iirc,稍后会解释几个教训。

答案 2 :(得分:2)

以下是Kipton的建议和我自己的建议:

trait List[+T] {
  def isEmpty: Boolean
  def head: T
  def tail: List[T]
}
class Cons[+T](val head: T, val tail: List[T]) extends List[T] {
  def isEmpty = false
}
case object Nil extends List[Nothing] {
  def isEmpty = true
  def head = throw new NoSuchElementException("Nil.head")
  def tail = throw new NoSuchElementException("Nil.tail")
}
object ListTest {
  def main(args: Array[String]) {
    val lst = new Cons("A", new Cons("B", new Cons("C", Nil)))
  }
}
不过,您的代码无法使用我的Scala安装进行编译。应用程序实现“主”,因此您必须覆盖它或(因为应用程序的意图)将其删除。

请注意,您需要ListCons是协变的(例如List[+T]),这基本上意味着对于T的子类型U,它还认为List[U]是一个List[T]的子类型,扩展名为List [Nothing]是列表的子类型。