scala - 在 akka 消息中保留类型/类标签

标签 scala generics akka

我有这样的情况,我想保留有关在消息中传递的某些泛型类型的信息,以便能够在负责处理消息的接收方法中创建另一个具有相同类型的泛型类。

乍一看,我认为 TypeTag 是我最好的 friend ,但是,在尝试之后,这似乎不是最好的解决方案,或者根本不是解决方案。让我先解释一下我现在有什么,结果是什么。

消息案例类

trait MessageTypeTag[T] {
  def typeTag: TypeTag[T]
}

case class Message[T](id: Int, payload: T, helper: MyClass[T], 
                      cond: Condition[MyClass[T]])(implicit val typeTag: TypeTag[T])
           extends MessageTypeTag[T]

MyClass2

class MyClass2[+T <: Any](_eval: Option[T] = None) {
  def getEval = _eval getOrElse None
}

接收方式

def receive() = {
  case m@Message(id, payload, helper, cond) => {
    // this prints a proper type tag, i.e. String, because type is known in the runtime
    println(m.typeTag.tpe)

    // compiler complains here because it sees m.typeTag as TypeTag[Any], i.e. exact
    // type is not known in the compile time
    val temp = new MyClass2[m.typeTag.tpe](...)
 }
}

肮脏的解决方案 在阅读了几篇关于 Scala 和 akka 的文章、讨论和文档之后,我通过放置(调用)工厂方法案例类提出了一些肮脏的解决方案。

case class Message[T](id: Int, payload: T, helper: MyClass[T], 
                      cond: Condition[MyClass[T]])(implicit val typeTag: TypeTag[T])
           extends MessageTypeTag[T] {
  def getMyClass2: MyClass2[T] = {
    // instantiate an object of type T
    val bla = typeTag.mirror.runtimeClass(typeTag.tpe).newInstance.asInstanceOf[T]
    // we can call apply here to populate created object or do whathever is needed
    ...
    // instantiate MyClass2 parametrized with type T and return it
    new MyClass2[T](Some(bla))
  }
}

如您所见,这远非好的解决方案/设计,因为这个案例类几乎是轻量级的,实际上违背了案例类本身的目的。它可以通过以下方式改进:反射调用未在此处编码,而是在一些仅在案例类中调用的外部工厂中编码,但我觉得必须有更好的方法来实现这一点。

如有任何建议,我们将不胜感激。如果需要更多信息,我可以提供。

而且,我相信,已经描述了类似的问题/解决方案 here ,但我想知道是否有更好的方法。谢谢。

最佳答案

如果你想用反射来实例化一个类,那么你必须传递它,没有办法绕过它。我认为基于 ClassTag 的解决方案稍微简单一些:

val bla = classTag.runtimeClass.newInstance.asInstanceOf[T]

但还是很丑。

将工厂作为函数传递可能比使用反射方法更好;这使您可以使用没有无参数构造函数或需要一些设置的类:

case class Message[T](..., factory: () => T) {
  def getMyClass2 = new MyClass2[T](Some(factory()))
}

Message(..., {_ => new SomeTThatTakesArguments(3, 4)})

我怀疑最好的解决方案是更改您的 MyClass2 以使其不以相同的方式依赖于类型 - 也许您可以表达约束 MyClass2 needs 作为类型类,您可以将其包含在 Message 中,也可以将其完全忽略。但是,如果您希望我们针对这些行提出解决方案建议,则需要发布 MyClass2

关于scala - 在 akka 消息中保留类型/类标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26479587/

相关文章:

java - 作为原始类型 Comparator 的成员对 Compare(T,T) 进行未经检查的调用

ios - 两个用 NSIndexPath 填充的通用数组的补充/交集

actor - Akka 2 : How to pause processing of messages?

scala - 可以在 Akka FSM 中匹配多个接收到的消息

scala - 用一个枚举器提供两个迭代器

scala - 无法调用接受并返回特征中自引用参数化类型对象的函数

scala - 我应该只使用现代 Akka 从 Actor 内部发送 Actor 消息吗?

scala - 使用 Slick 创建参数化准备语句

java - 使用 lambda 会阻碍类型变量的推断

scala - 案例类和案例对象之间的区别?