Option
两种启动对象的方式的优缺点是什么:
1.
def getAmount: Option[Int] = {
val a: Int = 1
Option(a)
}
2.
def getAmount: Option[Int] = {
val a: Int = 1
Some(a)
}
我应该使用哪个?
Option
两种启动对象的方式的优缺点是什么:
1.
def getAmount: Option[Int] = {
val a: Int = 1
Option(a)
}
2.
def getAmount: Option[Int] = {
val a: Int = 1
Some(a)
}
我应该使用哪个?
有两个重要的区别。首先,如果其参数为空,Option
则返回 a :None
scala> val x: Option[String] = Some(null)
x: Option[String] = Some(null)
scala> val y: Option[String] = Option(null)
y: Option[String] = None
这可能很有用,但它并不总是您想要的,并且(同样重要的是)它表明在某些情况下该参数可能为 null 的可能性很大,这可能会产生误导。
Some
更适合您想要生成一个Option
您知道不为空的值的情况。不幸的是,第二个区别是Some(foo)
is Some[Whatever]
, not的返回类型Option[Whatever]
,这在某些情况下可能非常不方便,因为Some
推断意味着您在尝试使用时None
或Option
稍后在某些位置会遇到类型错误。在这些情况下,您必须使用Some(foo): Option[Whatever]
,这非常令人不快。
例如,假设我们有一个表示(我们希望)整数的字符串列表,并且我们想要对它们进行解析和求和。None
如果有解析错误,我们想要一个,Some(total)
否则。以下是使用标准库在单次遍历中执行此操作的相当合理的方法:
List("1", "2", "3").foldLeft(Some(0)) {
case (acc, item) => for {
t <- acc
n <- util.Try(item.toInt).toOption
} yield t + n
}
除了这不起作用——我们得到一个类型错误:
<console>:10: error: type mismatch;
found : Option[Int]
required: Some[Int]
t <- acc
^
我们可以通过写作来解决这个问题.foldLeft(Some(0): Option[Int])
,但是,呃。
这在您的特定示例中不是问题,因为返回类型是显式的Option[Int]
,因此您无需担心类型推断。在这种情况下Some(a)
是正确的选择。
附带说明一下,Scalaz提供了some
构造none
函数来帮助您避免类型推断问题和嘈杂的解决方案,例如Some(foo): Option[Whatever]
:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> some(10)
res0: Option[Int] = Some(10)
scala> none[Int]
res1: Option[Int] = None
两种返回类型都是Option
,这使得类型推断更容易。如果您不想使用 Scalaz,您可以自己定义这些:
scala> def some[A](a: A): Option[A] = Some(a)
some: [A](a: A)Option[A]
scala> def none[A]: Option[A] = None
none: [A]=> Option[A]
如果您使用这些来代替,Some
那么None
您永远不必担心会推断出不恰当的特定类型。
总结一下:Option(foo)
仅在参数可能为空的情况下使用(理想情况下,这应该只用于与 Java 的互操作性)。Some(foo)
在值已显式键入为 的情况下使用Option
。如果推断的类型是Some[Whatever]
,请添加: Option[Whatever]
类型注释,或使用类似 Scalaz 的some
.
对我来说,这只是一个常识问题。当然你可以想象这样的情况,你期望某些类型的东西是 Some and None 是不允许的。但通常第二种方式看起来更自然:返回类型是 Option,实际实现是 Some(x) 或 None。从技术上讲,从源代码中,Option(x) 调用apply()
伴随对象的方法:
object Option {
import scala.language.implicitConversions
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
def apply[A](x: A): Option[A] = if (x == null) None else Some(x)
def empty[A] : Option[A] = None
}
并且 Some(a) 在案例类上调用apply()
方法..
final case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
所有其他方法都是一样的。Travis Brown的回答null
很好地解释了对象的用例。