我有一个特征并且实现了akka actor,由于类型擦除而无法正确区分传入消息的类型,因此第一种情况是匹配所有消息。
我正在使用scala 2.10.x,并且从阅读许多其他答案我知道可以使用TypeTag
或ClassTag
恢复特征内的类型信息,但我无法想象如何在akka接收中应用它(如果可能的话)。
我(非常简化)的例子如下。是否可以正确匹配泛型类型?
package com.ebay.box.canada.batch.jobs.siteMap
import akka.actor.Actor
import akka.actor.ActorSelection
import akka.actor.Actor.Receive
import scala.reflect.ClassTag
trait MessageProcessor[A,B] {
this: Actor =>
val destA: ActorSelection
val destB: ActorSelection
def processA(a: A): A
def processB(a: B): B
def receive: PartialFunction[Any,Unit] = {
case a: A =>
destA ! processA(a)
case b: B =>
destB ! processB(b)
}
}
class StringIntProcessor(val destA: ActorSelection, val destB: ActorSelection) extends MessageProcessor[String,Int] with Actor {
def processA(a: String) = { a + "1" }
def processB(b: Int) = { b + 1 }
}
答案 0 :(得分:0)
我不认为你可以在你的特征中获得TypeTag[A]
或ClassTag[A]
- 类型标签/类标签始终是方法调用的隐式参数列表的一部分。您可以使用隐式构造函数参数来使用抽象类:
import scala.reflect.runtime.universe._
abstract class MessageProcessor[A,B]()(implicit cta: ClassTag[A], ctb: ClassTag[B]) {
def receive = {
case a: Any if a.getClass() == cta.runtimeClass =>
process(a.asInstanceOf[A])
...
}
...
}
(未经测试!)
假设您可以更改发送消息的代码,我可以建议使用以下设计吗? MessageProcessor现在是一个类型类,因此您可以添加任意数量的消息类型。通过发送闭包作为消息,您可以将任意数量的上下文走私到呼叫站点。
class MessageReceiver extends Actor {
def receive = {
case fn: Function0[Unit] =>
fn()
}
}
trait MessageProcessor[A] {
val dest: ActorSelection
def process(a: A): A
}
object Processors {
implicit object StringProcessor extends MessageProcessor[String] {
val dest: ActorSelection = Wellknown.stringDest
def process(a: String): String = a + "1"
}
implicit object IntProcessor extends MessageProcessor[Int] {
val dest: ActorSelection = Wellknown.intDest
def process(a: Int): Int = a + 1
}
def sendMessage[A](msg: A)(implicit ev:[MessageProcessor[A]]): Unit = {
val block: Function0[Unit] = { () =>
ev.dest ! ev.process(msg)
}
val msgDest = system.actorOf[Props[MessageReceiver]], "msgDest")
msgDest ! block
}
}
(也未经过测试!)