Scala-具有通用参数的抽象消息处理程序

时间:2018-09-11 17:16:21

标签: scala generics aws-lambda

我将Scala与AWS lambda结合使用,处理不同类型的事件。每个“处理程序”类都是一个不同的lambda处理程序,将仅用于一种类型的消息,但是为了共享通用的处理代码,我将内容汇总为抽象类+特征

当需要将特定于每种消息类型的处理移交给子类时,我最终得到了一个抽象方法,我仍然需要对消息的类型进行模式匹配,如果出现这种情况,则总是记录某种错误错误的消息类型使其变成处理程序子类型。

这些默认情况似乎是多余的,因为错误的消息类型永远不会到达错误的处理程序子类型。

这是我所拥有的简化版本

trait Message {
    val text: String
}

case class MessageA(text: String, errorCode: Int) extends Message
case class MessageB(text: String, url: String) extends Message

abstract class MessageHandler {
  protected def processMessage(message: Message)

  ...
}

//Lambda handler 1
class MessageAHandler extends MessageHandler {

  override protected def processMessage(message: Message) = message match {
    case a: MessageA => handleErrorCode(a.errorCode)
    case _ => //log some error - This should never be reached
  }

  ...
}

//Lambda handler 2
class MessageBHandler extends MessageHandler {
  override protected def processMessage(message: Message) = message match {
    case b: MessageB => handleUrl(b.url)
    case _ => //log some error - This should never be reached
  }

  ...  
}

我尝试用类型限制实现processMessage调用,但这似乎并没有太大的区别,我仍然需要在'M'上进行模式匹配以确定message参数的子类型,因此可以这样对待。

protected def processMessage[M <: Message](message: M)

有人必须做类似的事情吗?有没有更清洁的方式做到这一点?

2 个答案:

答案 0 :(得分:0)

您可以将Message类型抽象为基本类型:

abstract class MessageHandler {
  type Msg <: Message
  protected def processMessage(message: Msg)
}

class MessageAHandler extends MessageHandler {
  type Msg = MessageA
  protected def processMessage(message: MessageA) = 
    handleErrorCode(message.errorCode)
}

但是我不确定从调用站点(调用processMessage的代码)之后是否易于处理。模式匹配可能只在那儿移动(但总体上可能会更优雅)。

答案 1 :(得分:0)

您可以在此处使用继承。将代码放入特质中处理消息,然后让多态为您完成工作。

trait Message {
  val text: String
  def handleMessage
}

case class MessageA(text: String, errorCode: Int) extends Message
{
  override def handleMessage = handleErrorCode(errorCode)
}

case class MessageB(text: String, url: String) extends Message
{
  override def handleMessage = handleUrl(url)
}

case object MessageHandler 
{
  def processMessage(message: Message) = message.handleMessage
}