内部模式上的 Scala 语法模式匹配



我需要用内部对象分解案例类,并且案例变得非常长,无法编写。假设我只考虑由其类型分解的"上下文"的内部对象的第一个参数,有没有更好的方法来编写这个?


编辑:更改了示例以反映讨论

    // context should be any opaque type that you want returned to you in your result message
  case class PopulateFeedVersionMessage(inoutContext: Any, sectionId : Int, feedId : Int, newVersion : String, oldVersion : String)

  trait PopulateDBReturnableMessage {
    val inputMessage : PopulateFeedVersionMessage
  }
  case class PopulateFeedFileNotExistsError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage
  case class PopulateFeedUploadError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage
  case class PopulateFeedRuntimeError(inputMessage : PopulateFeedVersionMessage, errorMessage : String) extends PopulateDBReturnableMessage
  case class PopulateDBResult(inputMessage: PopulateFeedVersionMessage, localNewDBPath : String, localOldDBPath : String, feedType : DatafeedType) extends PopulateDBReturnableMessage

假设在父演员中,我这样做:

childActor ! PopulateFeedVersionMessage(inoutContext = interestingContextObjectForThisParticularMessage,sectionId = 1, feedId = 2, newVersion = "Some new version", oldVersion = "some old version")

在子演员中,我处理消息并决定使用 PopulateDBReturnableMessage 类型(可以是 resulterror 类型)进行响应

 // child
override def receive = {
    case message : PopulateFeedVersionMessage => sender ! handle(message)
  }
def handle(message : PopulateFeedVersionMessage) = {
...
// lets say we had an upload error because the disk is full or 401 or server down or what ever we can supply in the error message
  PopulateFeedUploadError(inputMessage = message, errorMessage : "The disk is full")
} 

现在回到父演员:

def receive = {
  case MessageType1 => {
    ... deciding what to do...
    ... decided to spawn a child actor with a context of interest...
    childActor ! PopulateFeedVersionMessage(inoutContext = interestingContextObjectForThisParticularMessage,sectionId = 1, feedId = 2, newVersion = "Some new version", oldVersion = "some old version")
  }
  // async handling the return message of the child with the context
  case m : PopulateDBReturnableMessage => m match {
      case PopulateFeedFileNotExistsError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case PopulateFeedUploadError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {
      }
      case PopulateFeedRuntimeError(inputMessage: PopulateFeedVersionMessage, errorMessage: String) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case PopulateDBResult(inputMessage: PopulateFeedVersionMessage, localNewDBPath: String, localOldDBPath: String, feedType: DatafeedType.DatafeedType) => {
        // need to decompose the inputMessage.context as a inInterestingContextObjectForThisParticularMessage type
      }
      case _ =>
    }
}

您可以实现自定义匹配器(例如 InoutContext如下)将PopulateFeedVersionMessage分解为inoutContext

  object InoutContext {
    def unapply(obj: PopulateFeedVersionMessage): Option[Any] = 
      Some(obj.inoutContext)
  }

然后,您可以像这样进行模式匹配:

 case PopulateFeedFileNotExistsError(
        InoutContext(strCtx: String), 
        errorMessage
      ) => {
   ...
  }