如何重写以下内容以使其更加“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
}
还有其他方法吗?
答案 0 :(得分:1)
这一切都可以在一个大模式匹配中完成:
fooOpt match {
case Some(Foo(_: Int | _: String)) => doSomething
case _ => doSomethingElse
}
如果您想要Int
或String
,请将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)
因此,在这种情况下,编译器会为您检查类型,回答:
是否可以直接检查酒吧的类型?
在许多情况下,您可以使用map
,orElse
等方法进行正确输入,从而避免使用模式匹配。这可能是一个答案:
也可以重写只使用一个案例