Akka 中 case 类 有什么特别之处?

What is special about case classes in Akka?

我读过 classes 可以与模式匹配一​​起使用。但是,我也可以使用带有模式匹配的常规 class。 This question 给出了常规的 Scala 视角。我希望从 scala 和 akka 的角度来看这个特定的代码。 例如:

演员class:

class TestActor extends Actor {

  def receive={
    case One(num)=>println("One "+num)
    case t:Two=>println("Two "+t.num)
    case _=>println("Another")
  }
}

object TestActor{
  case class One(num:Int)
}

Class二:

class Two(var num:Int){  }

主要:

object Main2 extends App{

  val system=ActorSystem("t")
  val testActor=system.actorOf(Props[TestActor],"test")

  val t=new Two(200)
  val o=TestActor.One(100)

  testActor!o
  testActor!t

}

输出为:

One 100
Two 200

我知道我在这里遗漏了一些东西,可能是我对模式匹配的理解。有人可以帮我吗?

正如您所注意到的,与 Akka 中的 case classes 的主要区别是在匹配时能够使用它们的提取器(不应用方法)(除了您从我们的 case [= 中获得的通常功能之外) 33=]es,例如 hashCodeequals 的实现,并将它们作为产品类型使用)。

通过一个更大的示例,您可以看到效果如何。例如,假设您正在使用 Akka-HTTP 客户端向第三方服务发出 HTTP 请求,并且您希望在收到 StatusCode.OK 或任何其他状态代码时进行不同的操作。因为 HttpResponse 提供了一个 unapply 方法,你可以这样做:

case HttpResponse(StatusCodes.OK, _, entity, _)) => // We're good, parse the data.
case HttpResponse(statusCode, _, _, _)) => // Operate on status code != OK

而不是:

case response: HttpResponse =>
  if (response.statusCode != StatusCodes.OK) {
    // Stuff
  }
  else {
    // Other stuff
  }

当您的逻辑变得更加复杂时,仅提取您想要的值可能会非常有用并且不会那么冗长。在我们的代码库中,我们有一些更复杂的多值,比如:

case (Foo(bar, baz), resp@HttpResponse(statusCode, _, _, _))

当然,您始终可以自己在伴随对象中创建一个 unapply 方法,并自己获得与案例相同的语义 class,但您通常不想这样写样板文件,允许编译器为您完成。

总而言之,在 Akka 中使用 case class 作为数据容器简化了模式匹配的工作,这通常是您在实现 receive 方法时所做的。