我有以下抽象类:
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。我该如何解决这个问题?
答案 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
作为有效的子类型。为了使我们保留MyList
和Empty
之间的“ 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
}