首页 > 解决方案 > Scala - 具有通用参数的抽象消息处理程序

问题描述

我将 Scala 与 AWS lambdas 一起使用,处理不同类型的事件。每个“处理程序”类都是一个不同的 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”上进行模式匹配以确定消息参数的子类型,因此可以这样对待。

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

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

标签: scalagenericsaws-lambda

解决方案


您可以将 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)处理。模式匹配可能只是移动到那里(但总体上可能仍然更优雅)。


推荐阅读