4

我正在尝试使用该Option.getOrElse()方法,但它返回 etiherAny或而不是参数化ScalaObject的正确类的实例。Option我找不到有关此问题的任何提及,而且似乎不应该存在。我究竟做错了什么?

class MyClass {

  def isOk = true

}

val myVal = Some(new MyClass) // :Option[MyClass]

val check = myVal.getOrElse(false).isOk

无法调用该isOk方法,因为它尝试调用它Any

4

7 回答 7

17

您正在尝试在( )isOk的基类上MyClass调用方法。BooleanAny

尝试这个:

scala> class MyClass(b: Boolean) { def isOk = b }
defined class MyClass

scala> val myVal = Some(new MyClass(true))
myVal: Some[MyClass] = Some(MyClass@35d56bbe)

scala> myVal.map{_.isOk}.getOrElse(false)
res0: Boolean = true

scala> myVal.getOrElse(new MyClass(false)).isOk
res1: Boolean = true
于 2012-05-22T11:09:04.323 回答
8

按设计工作。这个表达式:

myVal.getOrElse(false)

返回未包装的MyClass实例或(如果Option实际上是None) - falseMyClass和的唯一常见类型Boolean是...... Any这就是你所看到的。

为了使其工作,您必须返回与MyClassfrom兼容的内容getOrElse()

myVal.getOrElse(new MyClass).isOk

或者,也许您想实现空对象模式:

object MyClass {
  val Empty = new MyClass
}

myVal.getOrElse(MyClass.Empty).isOk
于 2012-05-22T11:08:24.293 回答
6

您正在使用布尔值在 Option[MyClass] 中应用 getOrElse,因此,它们的通用超类是 Any。

你应该模式匹配:

val check = myVal match {
  case Some(c) => c.isOk
  case None => false
} 
于 2012-05-22T11:10:24.247 回答
4

您正在getOrElse调用Option[MyClass]. 您将 aBoolean作为参数传递给getOrElse. 发生的事情是 Scala 正在将选项转换为Option[Any],因为是andAny的最具体的常见类型。MyClassBoolean

将一个MyClass(或一个子类MyClass)传递给getOrElse而不是false

于 2012-05-22T11:08:34.507 回答
1

因此,当 Optional 值为 时,您有一个Option[A], 和一个函数A => B,以及一个默认值,并且您希望以 . 结尾。(在你的情况下,是和是)。BNoneBAMyClassBBoolean

作为一个 Haskeller,我想做的第一件事就是胡说八道。回想一下,在 Haskell 中,Option称为Maybe. 所以我们hoogleMaybe a -> (a -> b) -> b -> b,最热门的是maybe :: b -> (a -> b) -> Maybe a -> b,这正是我们想要的。

data MyClass = MyClass { isOK :: Bool }
newMyClass = MyClass { isOK = true }

myVal = newMyClass
check = maybe False isOK myVal

好吧,这很好,但是 Scala 呢?好吧,相当于 hoogle 的 Scala 是Scalex。我搜索了 Scalex Option[A] => B => (A => B) => B,但无济于事。因此,让我们看看这个maybe函数是如何在 Haskell 中实现的。您可以通过 hoogle 的相应链接找到源代码。

maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing  = n
maybe _ f (Just x) = f x

似乎很容易翻译成 Scala

def option[A, B](opt: Option[A])(n: B)(f: A => B) = opt match {
  case None => n
  case Some(x) => f(x)
}

然后可以像这样使用它:

val check = option(myVal)(false)(_.isOK)

如果你想用更少的柯里化或拉皮条 Option 类来做到这一点,你将不得不询问比我更精通 Scala 的人,但请注意这基本上归结为 Jhonny Everson 建议的模式匹配。

于 2012-05-22T15:41:44.323 回答
1

因为您的 getOrElse 可能返回 false,所以 MyClass 和 false 的常见类型是 Any。

于 2012-05-22T11:08:49.673 回答
1

强尼·埃弗森是对的。模式匹配就是答案。在这种情况下,他的答案中的模式相当于exists

scala> Some(new MyClass) :: None :: Nil map(_.exists(_.isOK))
res12: List[Boolean] = List(true, false)
于 2012-05-22T14:57:45.897 回答