我如何绕过 Akka 接收方法的类型擦除
How do I get around type erasure on Akka receive method
我在 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)
现在我有了为每种类型的事件执行操作的特征:
摘要:
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 种从 Event 扩展而来的事件。
我想在单独的特征中为每个事件实现业务逻辑,因为混合所有 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 内部实现业务逻辑。
我正在寻找某种基于设计模式的通用解决方案,例如策略模式。
首先,我建议您将事件定义为:
sealed trait Event { def timeStamp: Long }
case class StudentEvent(timeStamp: Long, studentId: Long)
extends Event
case class TeacherEvent(timeStamp: Long, teacherId: Long)
extends Event
这是代数数据类型的标准编码。
其次,您使用自我类型的这项业务让我感到很困惑。当然,同一个对象不应该既是 "actor" 又是 "action"?为什么不在这里使用组合而不是继承呢? (有点像你只是把 Scala 功能放在一起。所以这里的一般建议是:放慢速度。)
但要解决您的主要问题,我认为您基本上走错了路。几乎任何时候你最终都会与类型擦除 and/or TypeTag
发生冲突,这表明你的设计存在缺陷,你应该后退并重新思考——除非你真的很清楚自己在做什么。
在任何情况下,您都无法让 Akka 将 TypeTag
附加到您的消息中。 Akka 不是那样工作的。 (已经有一系列努力将 "typed actors" 或 "typed channels" 添加到 Akka,您可能会查看这些内容,但在您的用例中它可能有点矫枉过正,除非您非常确定它不是。 )
您要在这里解决的基础架构问题是什么?这个设计的动机是什么?
看看Composing trait behavior in Scala in an Akka receive method,好像真的很像,消化之后,我想你会更好地决定下一步该怎么做。
我在 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)
现在我有了为每种类型的事件执行操作的特征:
摘要:
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 种从 Event 扩展而来的事件。
我想在单独的特征中为每个事件实现业务逻辑,因为混合所有 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 内部实现业务逻辑。
我正在寻找某种基于设计模式的通用解决方案,例如策略模式。
首先,我建议您将事件定义为:
sealed trait Event { def timeStamp: Long }
case class StudentEvent(timeStamp: Long, studentId: Long)
extends Event
case class TeacherEvent(timeStamp: Long, teacherId: Long)
extends Event
这是代数数据类型的标准编码。
其次,您使用自我类型的这项业务让我感到很困惑。当然,同一个对象不应该既是 "actor" 又是 "action"?为什么不在这里使用组合而不是继承呢? (有点像你只是把 Scala 功能放在一起。所以这里的一般建议是:放慢速度。)
但要解决您的主要问题,我认为您基本上走错了路。几乎任何时候你最终都会与类型擦除 and/or TypeTag
发生冲突,这表明你的设计存在缺陷,你应该后退并重新思考——除非你真的很清楚自己在做什么。
在任何情况下,您都无法让 Akka 将 TypeTag
附加到您的消息中。 Akka 不是那样工作的。 (已经有一系列努力将 "typed actors" 或 "typed channels" 添加到 Akka,您可能会查看这些内容,但在您的用例中它可能有点矫枉过正,除非您非常确定它不是。 )
您要在这里解决的基础架构问题是什么?这个设计的动机是什么?
看看Composing trait behavior in Scala in an Akka receive method,好像真的很像,消化之后,我想你会更好地决定下一步该怎么做。