【问题标题】:How do I get around type erasure on Akka receive method如何绕过 Akka 接收方法的类型擦除
【发布时间】:2015-02-05 06:15:55
【问题描述】:

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

我有几种类型的事件:

 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)

现在我有了为每种类型的事件实现动作的特征:

摘要:

trait Action[T <: Event] {   
  def act[T](event:T):Unit
}

还有两个实现:

trait StudentAction extends Action[StudentEvent]{
  override def act[StudentEvent](event:StudentEvent):Unit = println(event)
}

trait TeacherAction extends Action[TeacherEvent]{
  override def act[TeacherEvent](event:TeacherEvent):Unit = println(event)
}

现在我的演员:

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

  override def receive= {
    case msg: T => act(msg)
    case _ => println("Unknown Type")
  }
}

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

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

编译时出现错误:

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

我知道我需要以某种方式使用 TypeTag,但我不明白该怎么做。

请帮忙。

更新:

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

我想在单独的 trait 中为每个事件实现业务逻辑,因为混合所有 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
   }
}  

和同一个Event3Actor、Event4Actor等......

这样的代码在我看来很难看,因为我需要在每个 Actor 内部实现业务逻辑。

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

【问题讨论】:

    标签: scala dependency-injection akka


    【解决方案1】:

    首先,我建议将您的事件定义为:

    sealed trait Event { def timeStamp: Long }
    case class StudentEvent(timeStamp: Long, studentId: Long)
      extends Event
    case class TeacherEvent(timeStamp: Long, teacherId: Long)
      extends Event
    

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

    其次,你使用自我类型的这个业务对我来说似乎真的很困惑。当然,同一个对象不应该既是“演员”又是“动作”?为什么不在这里使用组合而不是继承? (这有点像你只是把 Scala 的功能放在一起。所以这里的一般建议是:放慢速度。)

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

    在任何情况下,您都无法让 Akka 将 TypeTag 附加到您的消息中。 Akka 只是不能那样工作。 (为了向 Akka 添加“类型化的actor”或“类型化的通道”已经进行了一系列努力,您可能会查找这些内容,但在您的用例中这可能是多余的,除非您确定不是这样。)

    您在这里要解决的基本架构问题是什么?这个设计的动机是什么?

    查看Composing trait behavior in Scala in an Akka receive method,看起来真的很像,消化之后,我想你会更好地决定下一步该做什么。

    【讨论】:

    • 你的新问题很有说服力。我建议将其作为一个全新的独立问题提出。
    猜你喜欢
    • 2023-03-31
    • 2013-12-23
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多