我在阿卡发现了一些奇怪的行为。当我匹配模式时,我无法将消息添加到列表中:
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 _ =>
}
这是Scala
还是Akka
中的错误?
要修复它,我需要案例类型
msgs = msgs.::(msg.asInstanceOf[Message])
这不是一个方便的解决方案。
问题是您在case语句中发生的匹配中犯了一个微妙的错误。您在那里匹配的是Message
伴随对象,而不是Message
case类。
另一种看法是,case x @ Y
语法可以被认为是"与类型Y
的任何实例匹配,然后运行等效的val x: Y = <incoming value>.asInstanceOf[Y]
",但这里您提供的推断类型是一种称为Message
的无参数类型,编译器认为它是object Message
,而不是case class Message()
。
因此,要修复该行,请在参数列表中写入。例如,如果Message
类定义为:
case class Message()
这将是:
case msg @ Message() => ...
如果我们有,说:
case class Message(text: String, id: Int)
然后case语句变成类似于:
case msg @ Message(txt, is) => ...
或者,如果我们不关心(或需要使用)text
和id
参数:
case msg @ Message(_, _) => ...
为了在技术上更准确地描述这里发生的事情,case语句实际上是在尝试与伴随对象(也称为"提取器")中可用的任何"不适用"方法进行匹配。默认情况下,对于与case类构造函数中提供的参数列表完全匹配的任何case类,将在伴随对象中免费提供apply
和unapply
方法。在上面Message
类的第二个版本中,相关的unapply
方法将具有如下签名:
def unapply(text: String, id: Int): Option[Message]
你可以在这里和这里阅读更多关于提取器的信息。