我知道你可以匹配一组类似的东西,而不使用isInstanceOf
:
x match {
case fooBar @ (_: Foo | _: Bar) => ???
}
但是,有没有办法匹配除了一组类型之外的任何东西?比如,匹配不 x
或Foo
的任何Bar
,而不使用isInstanceOf
?
答案 0 :(得分:3)
嗯,你可以做到
x match {
case fooBar @(_: Foo | _: Bar) => // do nothing
default => // do something
}
无论如何,使用isInstanceOf
的唯一区别是语法,因为您将执行运行时检查。
从功能的角度来看,组合isInstanceOf
/ asInstanceOf
与类型匹配相同。
所以(如果你真的必须)我会选择
if (!(x.isInstanceOf[Foo] || x.isInstanceOf[Bar])) {
// do something
}
同样,没有实际的区别,它们都是处理类型的一种非常黑客的方式。除非您使用外部API而无法控制,否则我建议您更改设计并避免匹配类型。
通常类型类派上用场,但没有进一步的细节,很难确定。
答案 1 :(得分:1)
@GabrielePetronella的上述解决方案在大多数情况下都可以很好地工作,但是我添加了另一个可以在某些极端情况下提供帮助的变体。
由akka演员组成的Receive
函数。
考虑以下几点:
override def receive: Receive = handleFoo orElse handleBar
def handleFoo: Receive = {
case FooObject => …
case FooClass(value) => …
case notFoo =>
logger.debug(s"wasn't expecting $notFoo of type ${notFoo.getClass.getSimpleName}")
}
def handleBar: Receive = {
case _: VeryImportantBarMsg => …
case _: LessImportantBarMsg => …
}
handleFoo
的最后一种情况将捕获所有内容,从而使orElse handleBar
过时,并且显然我们不再处理VeryImportantBarMsg
或LessImportantBarMsg
。
使用专门的提取器对象,例如:
object NotBar {
def unapply[T](t: T): Option[T] = t match {
case _: VeryImportantBarMsg | _: LessImportantBarMsg => None
case _ => Some(t)
}
}
并像这样使用它:
def handleFoo: Receive = {
case FooObject => …
case FooClass(value) => …
case NotBar(notFoo) =>
logger.debug(s"wasn't expecting $notFoo of type ${notFoo.getClass.getSimpleName}")
}
此解决方案适用于您不希望匹配成功的情况,例如部分函数,akka接收,或者您发现自己多次写相同的排除类型列表_: T1 | … | _: T10
等。 ..
P.S。 如果您发现自己需要此解决方案,则很可能无法对某些模型进行最佳建模。在大多数情况下,可以避免这种情况。