Scala + Akka:类型上的模式匹配?

时间:2014-02-07 21:56:48

标签: scala pattern-matching akka

我们的代码库中包含这样的代码:

def receive: Receive = {
  case x: TypeX => doXishThingsWith(x)
  case y: TypeY => doYishThingsWith(y)
  case z: TypeZ => doZishThingsWith(z)
}

我发现需要为xyz提供一些愚蠢和令人困惑的名称。

我想知道这样的事情是否有效?

def receive: Receive = {
  case TypeX => doXishThingsWith(_)
  case TypeY => doYishThingsWith(_)
  case TypeZ => doZishThingsWith(_)
}

我不知道_是否真的以这种方式运作。但也许有类似的东西?

2 个答案:

答案 0 :(得分:6)

没有。 case a: A => m(a)是最短的解决方案。

使用case TypeX,您尝试匹配TypeX的随播广告对象,因此您必须使用下划线或变量名称:case _: TypeX

使用case _: TypeX您无法访问变量。

解决方法

实际上你可以使用没有变量名的方法,使用这样的魔法:

def receive: Receive = (
  pf[TypeX](doXishThingsWith) orElse
  pf[TypeY](doYishThingsWith) orElse
  pf[TypeZ](doZishThingsWith)
)

你必须像这样创建方法pf

import reflect.{ClassTag, classTag}

def pf[T: ClassTag](f: T => _): PartialFunction[Any, Unit] = {
  case e if classTag[T].runtimeClass.isInstance(e) => f(e.asInstanceOf[T])
}

示例:

class A; class B; class C

def mA(a: A) = println(s"mA!")
def mB(b: B) = println(s"mB!")

val receive = pf(mA) orElse pf(mB)

scala> receive.lift(new A)
mA!
res0: Option[Unit] = Some(())

scala> receive.lift(new B)
mB!
res1: Option[Unit] = Some(())

scala> receive.lift(new C)
res2: Option[Unit] = None

答案 1 :(得分:2)

你可以做经典多态:

trait T{
    def doThings()
}

class TypeX extends T{
    override def doThings() {
        println("doXishThingsWith")
    }
}

class TypeY extends T{
    override def do Things() {
        println("doYishThingsWith")
    }
}

def receive: Receive = {
  case x: T => x.doThings()
}

在模式匹配中使用下划线只意味着抛弃该值并且不能从任何变量

访问它