如何在Akka接收方法上绕过类型擦除

dan*_*nik 2 dependency-injection scala akka

我在Scala 2.10中使用蛋糕模式根据一些商业逻辑向我的演员注入所需的特征:

我有几种类型f事件:

 sealed abstract class Event(val timeStamp:Long)
  case class StudentEvent(override val timeStamp:Long, studentId:Long)  extends Event(timeStamp:Long)
  case class TeacherEvent(override val timeStamp:Long, teacherIdId:Long)  extends Event(timeStamp:Long)
Run Code Online (Sandbox Code Playgroud)

现在我有针对每种事件实现操作的特征:

抽象:

trait Action[T <: Event] {   
  def act[T](event:T):Unit
}
Run Code Online (Sandbox Code Playgroud)

两个推测:

trait StudentAction extends Action[StudentEvent]{
  override def act[StudentEvent](event:StudentEvent):Unit = println(event)
}
Run Code Online (Sandbox Code Playgroud)

trait TeacherAction extends Action[TeacherEvent]{
  override def act[TeacherEvent](event:TeacherEvent):Unit = println(event)
}
Run Code Online (Sandbox Code Playgroud)

现在我的演员:

class ActionActor[T <: Event] extends Actor{
  self:Action[T]=>

  override def receive= {
    case msg: T => act(msg)
    case _ => println("Unknown Type")
  }
}
Run Code Online (Sandbox Code Playgroud)

我以这种方式注入所需的特征:

 val actionActor =  system.actorOf(Props(new ActionActor[StudentEvent] with StudentAction))
 actionActor ! StudentEvent(1111L,222L)
Run Code Online (Sandbox Code Playgroud)

在编译时我收到错误:

Warning:(14, 14) abstract type pattern T is unchecked since it is eliminated by erasure
    case msg:T => act(msg)
         ^
Run Code Online (Sandbox Code Playgroud)

我知道我需要使用TypeTag,但我不明白我该怎么做.

请帮忙.

更新:

实际上,我有10种类型的事件,它从我需要处理的事件扩展而来.

我想在单独的特征中为每个事件实现业务逻辑,因为混合所有10个事件处理函数将给我数百(如果不是数千)行代码.

我不想为每个事件创建不同的Actor类型.例如:

class Event1Actor extend Actor{
  def receive ={
     case Event1(e) => //event1 Business Logic
   }
}

class Event2Actor extend Actor{
  def receive ={
     case Event2(e) => //event2 Business Logic
   }
}  
Run Code Online (Sandbox Code Playgroud)

和相同的Event3Actor,Event4Actor等....

这样的代码对我来说似乎很难看,因为我需要在每个Actor中实现业务逻辑.

我正在寻找基于设计模式的某种通用解决方案,例如策略模式.

Set*_*sue 7

首先,我建议将您的活动定义为:

sealed trait Event { def timeStamp: Long }
case class StudentEvent(timeStamp: Long, studentId: Long)
  extends Event
case class TeacherEvent(timeStamp: Long, teacherId: Long)
  extends Event
Run Code Online (Sandbox Code Playgroud)

这是代数数据类型的标准编码.

其次,你使用自我类型的这项业务似乎让我感到困惑.当然,同一个对象不应该既是"演员"又是"行动"?为什么不在这里使用组合而不是继承?(有点像你只是把Scala功能放在一起.所以这里的一般建议是:慢下来.)

但是为了解决你的主要问题,我认为你从根本上走错了路.几乎在任何时候你最终都会用类型擦除和/或者说TypeTag,这表明你的设计存在缺陷,你应该备份并重新考虑 - 除非你真的知道你在做什么.

在任何情况下,您都无法让Akka附加TypeTag到您的邮件.阿卡不是这样的.(已经有一系列努力向Akka添加"打字演员"或"打字频道",你可能会看一下这些,但是你的用例可能有点过分,除非你真的确定它不是.)

您在此尝试解决的基础架构问题是什么?是什么激发了这种设计?

在Akka接收方法中查看Scala中的组合特征行为,看起来非常相似,在消化之后,我认为您将能够更好地决定下一步该做什么.