简体   繁体   中英

Scala + Akka: pattern matching on type?

We have code like this scattered throughout our code base:

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

I find the need to give names to x , y and z kind of dumb and confusing.

I was wondering if something like this would work?

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

I have no idea if _ actually works this way. But maybe there is something similar?

No. case a: A => m(a) is the shortest solution.

With case TypeX you are trying to match on companion object of TypeX , so you have to use underscore or variable name: case _: TypeX .

With case _: TypeX you have no access to variable.

Workaround

Actually you could use methods without variable names using some magic like this:

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

You have to create method pf like this:

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])
}

Example:

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

you can do classical polymorphism:

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()
}

using underscore in pattern matching just means throw that value away and do not make it accessible from any variable

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM