如何让对象使用泛型扩展抽象类

时间:2019-02-26 08:30:20

标签: scala

我有以下抽象类:

abstract class MyList[A] {
  def head: A
  def tail: MyList[A]
  def isEmpty: Boolean
  def add(element: A): MyList[A]
  def printElements: String
  override def toString: String = "[" + printElements + "]"
}

我想扩展一个代表空列表的对象:

object Empty extends MyList {
  def head = throw new NoSuchElementException
  def tail = throw new NoSuchElementException
  def isEmpty: Boolean = true
  def add(element: A): MyList[A] = new Cons(element, Empty)
  def printElements: String = ""
}

但是我不知道如何从A内部正确到达类参数Empty。现在,我收到一个错误消息,因为未在Empty内定义符号A。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

A的空字符应该是底部类型,在Scala中称为Nothing

object Empty extends MyList[Nothing]

话虽如此,我们仍然需要对实现进行一些修改,以便进行编译。首先,我们需要在其类型参数中使A成为协变(稍后将对此进行进一步介绍):

abstract class MyList[+A]
class Cons[+A](val head: A, val tail: MyList[A]) extends MyList[A]

对于add,我们需要在A上创建一个lower bound才能使任何超类型都有效(请记住,Nothing是“继承”所有类型在Scala中,因为它是底部类型):

def add[B >: A](element: B): MyList[B]

现在我们可以实现Empty

object Empty extends MyList[Nothing] {
  override def head: Nothing = throw new NoSuchElementException

  override def tail: MyList[Nothing] = throw new UnsupportedOperationException("No tail for empty list")

  override def isEmpty: Boolean = true

  override def printElements: String = ""

  override def add[B >: Nothing](element: B): MyList[B] = new Cons[B](element, Empty)
}

由于add要求我们创建一个新列表,因此我们必须确保Cons接受Empty作为有效的子类型。为了使我们保留MyListEmpty之间的“ is子类型”关系,必须将该类型标记为协变。

答案 1 :(得分:-1)

这是您的代码版本,具有使其工作所需的最少修改,以及实现此编译所需的Cons实现:

abstract class MyList[+A] { // Added covariance
  def head: A
  def tail: MyList[A]
  def isEmpty: Boolean
  def add[B >: A](element: B): MyList[B] // Added second type parameter
  def printElements: String
  override def toString: String = "[" + printElements + "]"
}

// Added implementation of Cons
class Cons[+A](val head: A, val tail: MyList[A]) extends MyList[A] {
  self =>
  val isEmpty = false
  def printElements = ...
  def add[B >: A](element: B): MyList[B] = new Cons(element, self)
}

object Empty extends MyList {
  def head = throw new NoSuchElementException
  def tail = throw new UnsupportedOperationException("No tail for empty list")
  def isEmpty: Boolean = true
  def printElements: String = ""
  def add[A](element: A): MyList[A] = new Cons(element, Empty) // Added type parameter
}