如何在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
}
我如何在OOP世界中承担它:
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))
}
后者出了什么问题?
Functional programming in Scala在match
特征中使用Option[A]
,这是第三种方式(看起来像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] {
}
答案 0 :(得分:1)
我不确定您是否打算这样做,但是您遗漏了isEmpty
和get
的声明,这些声明是任何想要检查任意Option
内容的人所需要的无需向下转换为Some
。由于这两个方法都需要由两个子类定义,并且因为map
可以用它们来定义,我认为推理是在一个地方定义map
最好利用它其他方法的子类实现,而不是在三个地方定义map
。
答案 1 :(得分:0)
我想,因为scala支持功能和命令,并且它瞄准java程序,这是让它们更舒适的东西之一。
来自java程序员
val opt: Option[String] = ???
if (!opt.isEmpty) {
//do something with opt.get
} else {
//do some default...
}
可能比功能方式更容易理解(即使使用getOrElse)。
@Victor Moroz写了一篇关于使用模式匹配而不是this match { None => default_val; Some(v) => v }
的评论
除了新功能世界的程序员更难以阅读之外,这将花费更多,因为Option的用途很多,而且instanceOf的成本高于简单的if。