这是一个关于 Akka Cookbook 第 10 章“Enveloping actor”菜谱的问题。有人可以解释一下为什么我们不能只将“headers”函数作为参数传递,而必须在创建 envelopingActor 时将其作为“headers _”传递吗?
原始代码可以在这里找到:https://github.com/PacktPublishing/Akka-Cookbook/tree/master/Chapter10/src/main/scala/com/packt/chapter10
package com.packt.chapter10
import java.util.UUID
import akka.actor.{Actor, ActorRef, ActorLogging, ActorSystem, Props}
import Envelope._
object Envelope {
type Headers = Map[String, Any]
case class Envelope[T](msg: T, headers: Headers = Map.empty)
}
class EnvelopingActor(nextActor: ActorRef, addHeaders: Any => Headers) extends Actor {
def this(nextActor: ActorRef) =
this(nextActor, _ => Map())
override def receive: Receive = {
case msg => nextActor ! new Envelope(msg, addHeaders(msg))
}
}
class EnvelopeReceiver extends Actor with ActorLogging {
override def receive: Receive = {
case x => log.info(s"Received [$x]")
}
}
object EnvelopingActorApp extends App {
val actorSystem = ActorSystem()
val envelopeReceiver = actorSystem.actorOf(Props[EnvelopeReceiver], "receiver")
val envelopingActor = actorSystem.actorOf(
Props(classOf[EnvelopingActor], envelopeReceiver, headers _))
envelopingActor ! "Hello!"
def headers(msg: Any) = Map(
"t" -> System.currentTimeMillis(),
"cId" -> UUID.randomUUID().toString
)
}
最佳答案
如果您尝试删除 _
,您可能会看到如下错误:
Error:(379, 59) missing argument list for method headers in object EnvelopingActorApp
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writingheaders _
orheaders(_)
instead ofheaders
.
问题是,Props
是任何 Actor 参数集的通用容器。特别是它事先不知道会有多少个参数。所以它使用以下签名:
def apply(clazz: Class[_], args: Any*): Props
您可能会看到 args
的类型为 Any*
。此 *
意味着参数数量是可变的,并且每个参数都是 Scala 中可用的最通用类型 - Any
,它不是函数类型。
至于为什么 Scala 编译器在这种情况下不会自动将方法转换为函数类型 - 我认为答案是类型安全。想象一下,然后在某个时刻,您的 headers
不带任何参数(因此 headers
实际上是对该方法的调用),后来您将其修改为带一个参数。由于 Any
匹配任何类型,编译器无法注意到这实际上是一个重大更改(您已将就地调用更改为仅传递稍后可能调用的函数)。如果参数是某种函数类型的强类型,编译器可以注意到差异,从而可以安全地自动进行转换。
关于scala - 为什么在这种情况下不能将函数名称作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47746602/