Scala:与Option [Foo]和Foo参数匹配的模式

时间:2017-01-13 20:02:24

标签: scala pattern-matching scala-option

如何重写以下内容以使其更加“Scala方式”或只使用一个匹配?

case class Foo(bar: Any)
val fooOpt = Some(Foo("bar as String"))

def isValid(p: Any) = p match {
   case _ @ (_: String | _: Int) => true
   case _ => false
}

//Is it possible to check for the type of bar directly in this if statement?
fooOpt match {
    case Some(f) if isValid(f.bar) => doSomething
    case _ => doSomethingElse
}

一种替代方法是使用isInstanceOf。

fooOpt match {
     case Some(f) if f.bar.isInstanceOf[String] => doSomething
     case Some(f) if f.bar.isInstanceOf[Int] => doSomething //could also rewrite to use just one case
     case _ => doSomethingElse
}

还有其他方法吗?

2 个答案:

答案 0 :(得分:1)

这一切都可以在一个大模式匹配中完成:

fooOpt match {
   case Some(Foo(_: Int | _: String)) => doSomething
   case _ => doSomethingElse
}

如果您想要IntString,请将case分开:

fooOpt match {
   case Some(Foo(i: Int)) => doSomething
   case Some(Foo(s: String)) => doSomething
   case _ => doSomethingElse
}

答案 1 :(得分:1)

  

还有其他方法吗?

虽然有一个大模式匹配的解决方案可以使用(并且如果您真的无法将bar更改为比Any更具体的任何内容,则可以使用),这不是正确的&# 39; Scala方式'如果您可以控制Foo,则可以处理这种情况。

更好的方法是让Foo变得通用:

case class Foo[T](bar: T)

如果可以使用任何特定的doSomething,则可以使用通用T

def doSomething[T](foo: Foo[T]): SomeType = ???

或者为不同的T提供不同的版本,如果它应对它们做出不同的反应:

def doSomethingWithString(foo: Foo[String]): SomeType = ???
def doSomethingWithInt(foo: Foo[Int]): SomeType = ???

然后你可以像这样使用它:

val fooOpt = Some(Foo("bar as String"))
fooOpt.map(doSomething).orElse(doSomethingElse)

或者像这样:

val fooOptString = Some(Foo("bar as String"))
fooOptString.map(doSomethingWithString).orElse(doSomethingElse)

val fooOptInt = Some(Foo(1))
fooOptInt.map(doSomethingWithInt).orElse(doSomethingElse)

因此,在这种情况下,编译器会为您检查类型,回答:

  

是否可以直接检查酒吧的类型?

在许多情况下,您可以使用maporElse等方法进行正确输入,从而避免使用模式匹配。这可能是一个答案:

  

也可以重写只使用一个案例