如何使用匹配类型列表中的模式匹配结果?

How can I use the pattern matching result in the List of matching type?

我在 Akka 中发现了一些奇怪的行为。当我匹配模式时,我无法将消息添加到列表中:

  var msgs: List[Message] = Message() :: Nil

  ...

  override def receive: Receive = {
    case msg @ Message  => { 
      msgs = msgs.::(Message())   // ok
      //msgs = msgs.::(msg)       // doesn't work
      sender ! "Thanks!" 
    }
    case Request => { sender ! msgs.head }
    case _       =>
  }

这是 ScalaAkka 中的错误吗?

要修复它,我需要区分类型

msgs = msgs.::(msg.asInstanceOf[Message])

这不是一个方便的解决方案。

问题是您在 case 语句中发生的匹配中犯了一个微妙的错误。您在那里匹配 Message 伴随对象,而不是 Message 案例 class。

另一种看待它的方式是 case x @ Y 语法可以被认为是说 "match with any instance of type Y, and then run the equivalent of val x: Y = <incoming value>.asInstanceOf[Y]",但这里您提供的推断类型是一个称为 [=16] 的无参数类型=],编译器认为是 object Message,而不是 case class Message().

因此,要修复该行,请在参数列表中写入。例如,如果 Message class 定义为:

case class Message()

这将是:

case msg @ Message() => ...

如果我们有,说:

case class Message(text: String, id: Int)

然后 case 语句变成这样:

case msg @ Message(txt, is) => ... 

或者,如果我们不关心(或需要使用)textid 参数:

case msg @ Message(_, _) => ... 

为了从技术上更正确地描述这里发生的事情,case 语句实际上是在尝试与伴随对象(也称为 "extractors")中可用的任何 "unapply" 方法进行匹配。默认情况下,伴随对象中将免费提供一个 apply 和一个 unapply 方法,用于任何与案例 [=53= 中提供的参数列表完全匹配的案例 class ] 构造函数。在上面 Message class 的第二个版本中,相关的 unapply 方法将具有如下签名:

def unapply(text: String, id: Int): Option[Message]

您可以阅读有关提取器的更多信息here and here