【问题标题】:Preserving type arguments in Akka receive在 Akka 接收中保留类型参数
【发布时间】:2016-11-13 19:39:17
【问题描述】:

Roland Kuhn 在post 中已经回答了这个问题,然而,尽管有几位 cmets 询问细节,他并没有费心分享完整的答案。

这是我想要做的:我有一个包装类case class Event[T](t: T),我将其中的实例发送给 Akka 演员。在那个actor的receive方法中,然后我想区分Event[Int]Event[String],由于类型擦除,这显然不是那么简单。

Roland Kuhn 在上述帖子中分享的是“只有一种方法可以做到”,即在消息中体现类型信息。所以我这样做了:

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 方法应该是什么样子。

【问题讨论】:

  • 这看起来对我来说是正确的(除了直接比较 ClassTag 更简单:e.ct == ClassTag.Inte.ct == classTag[String])。在错误消息中,您有 s.ct,它不在代码中。
  • 将其更改为e.ct。我在这篇文章中将上面的代码简化为独立的。不过,我从真实代码中复制粘贴的错误消息。很好的收获,谢谢!
  • 您还需要修复case e: Event[_]。在此之后,它编译:scastie.org/23724.
  • 发布它作为答案!也许您可以详细说明在这种情况下如何使用速记符号Event[T : ClassTag]。另外,ClassTag.IntString 版本是什么?非常感谢,阿列克谢!
  • 已发布。在这种情况下,您不能使用T: ClassTag(好吧,您可以,但它最终会更加冗长)。 classTag[String] String 版本的ClassTag.Int

标签: scala akka type-erasure scala-reflect


【解决方案1】:

修复错误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!")
}

代码编译。不看ClassTags内部可以稍微简化一下(当然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!")
}

【讨论】:

    【解决方案2】:

    您还可以对嵌套类中的内部变量进行模式匹配,这样更简洁,您可以利用各种模式匹配技巧,甚至不需要 ClassTag:例如

    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")
    }
    

    【讨论】:

      猜你喜欢
      • 2023-01-12
      • 1970-01-01
      • 2021-11-10
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      相关资源
      最近更新 更多