在akka消息中保留类型/类标记



在这种情况下,我希望保留消息中传递的某个泛型类型的信息,以便能够在负责处理消息的receive方法中创建另一个具有相同类型的泛型类。

乍一看,我认为TypeTag是我在这里最好的朋友,但经过尝试,这似乎不是最好的解决方案,或者根本不是解决方案。让我首先解释一下我目前的情况以及结果如何。

消息用例类

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

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

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

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

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

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

但它还是很难看。

与其使用反思的方法,不如将工厂作为一种功能进行传递;这使您可以处理没有arg构造函数或需要一些设置的类:

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

我怀疑最好的解决方案是更改MyClass2,使其不以同样的方式依赖于类型——也许您可以将约束MyClass2表示为一个类型类,您可以将其包含在Message中,或者完全忽略它。但如果你想让我们就这些问题提出解决方案,你需要发布MyClass2

最新更新