它是如何在 Scala 中完成的:
sealed trait Option[+A] {
def get: A
def isEmpty: Boolean
def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
}
object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}
case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
Run Code Online (Sandbox Code Playgroud)
我如何在面向对象世界中假设它:
sealed trait Option[+A] {
def map[B](f: A => B): Option[B]
}
object None extends Option[Nothing] {
def map[B](f: Nothing => B): Option[B] = this
}
case class Some[+A](get: A) extends Option[A] {
def map[B](f: A => B): Option[B] = Some(f(get))
}
Run Code Online (Sandbox Code Playgroud)
后者有什么问题?
Scala 中的函数式编程使用matchin Option[A]trait,这是第三种方式(看起来像 Haskell,但为什么呢?)为什么不利用子类型多态?
更新:我提到的第三种方式:
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
}
object None extends Option[Nothing] {
}
case class Some[+A](get: A) extends Option[A] {
}
Run Code Online (Sandbox Code Playgroud)
我不确定您是否打算这样做,但是您遗漏了isEmpty和 的声明get,任何想要检查任意内容Option而不需要向下转换为 的人都需要这些声明Some。由于这两种方法都需要由两个子类定义,并且map可以根据它们进行定义,因此我认为原因是最好map在一个地方定义,利用其他方法的子类实现,而不是定义map在三个地方。