【问题标题】:Scala + Akka: pattern matching on type?Scala + Akka:类型的模式匹配?
【发布时间】:2014-03-05 12:01:30
【问题描述】:

我们的代码库中散布着这样的代码:

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

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

【问题讨论】:

  • 我希望 Scala 没有将模式匹配与类型调度混淆。

标签: scala pattern-matching akka


【解决方案1】:

没有。 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

【讨论】:

    【解决方案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()
    }
    

    在模式匹配中使用下划线只是意味着丢弃该值并且不要使其可从任何变量访问

    【讨论】:

    • 一般来说,给参与者的消息是没有额外领域逻辑的案例类。
    • 感谢关于下划线的建议;我试图通过在函数中使用它来移植我的知识(例如.map(_ + 2)
    猜你喜欢
    • 2021-05-13
    • 2020-08-09
    • 2018-06-20
    • 2015-01-17
    • 2013-03-17
    • 1970-01-01
    • 2019-04-20
    • 2013-12-01
    相关资源
    最近更新 更多