在 Akka 中保留类型参数接收
Preserving type arguments in Akka receive
Roland Kuhn 在这篇 post 中已经回答了这个问题,但是,尽管有几条评论要求提供详细信息,但他没有费心分享完整的答案。
这是我想要做的:我有一个包装器 class case class Event[T](t: T)
,我将其中的实例发送给 Akka actor。在那个actor的receive
方法中,我想区分Event[Int]
和Event[String]
,由于类型擦除,这显然不是那么简单。
Roland Kuhn在上述post中分享的是"there is exactly one way to do it",即在消息中体现类型信息。所以我这样做了:
case class Event[T](t: T)(implicit val ct: ClassTag[T])
即使不同的人要求提供它,Roland Kuhn 也没有说明在 receive
方法中实际做什么。这是我尝试过的。
def receive = {
case e: Event =>
if (e.ct.runtimeClass == classOf[Int])
println("Got an Event[Int]!")
else if (e.ct.runtimeClass == classOf[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
这是我能想到的最好的方法,因为很难完全理解 Scala 的反射丛林。但是它没有编译:
value ct is not a member of Any
else if (e.ct.runtimeClass == classOf[String])
^
因此,我特别询问 receive
方法应该是什么样子。
修复错误后Event takes type parameters
:
def receive = {
case e: Event[_] =>
if (e.ct.runtimeClass == classOf[Int])
println("Got an Event[Int]!")
else if (e.ct.runtimeClass == classOf[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
代码编译。不看ClassTag
可以稍微简化一下(当然ClassTag#equals
的实现是要对比类):
import scala.reflect.{ClassTag, classTag}
def receive = {
case e: Event[_] =>
if (e.ct == ClassTag.Int) // or classTag[Int]
println("Got an Event[Int]!")
else if (e.ct == classTag[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
你也可以在嵌套的内部变量上进行模式匹配 class 这样更简洁,你可以利用各种模式匹配技巧,你甚至不需要 ClassTag:eg
case class Event[T](t: T)
def receive = {
case Event(t: Int) =>
println("Int")
case Event((_: Float | _: Double)) =>
println("Floating Point")
case Event(_) =>
println("Other")
}
Roland Kuhn 在这篇 post 中已经回答了这个问题,但是,尽管有几条评论要求提供详细信息,但他没有费心分享完整的答案。
这是我想要做的:我有一个包装器 class case class Event[T](t: T)
,我将其中的实例发送给 Akka actor。在那个actor的receive
方法中,我想区分Event[Int]
和Event[String]
,由于类型擦除,这显然不是那么简单。
Roland Kuhn在上述post中分享的是"there is exactly one way to do it",即在消息中体现类型信息。所以我这样做了:
case class Event[T](t: T)(implicit val ct: ClassTag[T])
即使不同的人要求提供它,Roland Kuhn 也没有说明在 receive
方法中实际做什么。这是我尝试过的。
def receive = {
case e: Event =>
if (e.ct.runtimeClass == classOf[Int])
println("Got an Event[Int]!")
else if (e.ct.runtimeClass == classOf[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
这是我能想到的最好的方法,因为很难完全理解 Scala 的反射丛林。但是它没有编译:
value ct is not a member of Any
else if (e.ct.runtimeClass == classOf[String])
^
因此,我特别询问 receive
方法应该是什么样子。
修复错误后Event takes type parameters
:
def receive = {
case e: Event[_] =>
if (e.ct.runtimeClass == classOf[Int])
println("Got an Event[Int]!")
else if (e.ct.runtimeClass == classOf[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
代码编译。不看ClassTag
可以稍微简化一下(当然ClassTag#equals
的实现是要对比类):
import scala.reflect.{ClassTag, classTag}
def receive = {
case e: Event[_] =>
if (e.ct == ClassTag.Int) // or classTag[Int]
println("Got an Event[Int]!")
else if (e.ct == classTag[String])
println("Got an Event[String]!")
else
println("Got some other Event!")
case _ =>
println("Got no Event at all!")
}
你也可以在嵌套的内部变量上进行模式匹配 class 这样更简洁,你可以利用各种模式匹配技巧,你甚至不需要 ClassTag:eg
case class Event[T](t: T)
def receive = {
case Event(t: Int) =>
println("Int")
case Event((_: Float | _: Double)) =>
println("Floating Point")
case Event(_) =>
println("Other")
}