You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala for推导式匹配多case class时提取Trigger参数方案求教

解决方案

方案1:在sealed trait中定义统一访问方法(推荐,侵入性低易维护)

先修改Event trait的定义,增加默认返回None的triggerOpt方法,只有携带Trigger的子类重写该方法:

sealed trait Event {
  // 统一返回可选类型的Trigger,无该字段的子类默认返回None
  def triggerOpt: Option[Trigger] = None
}

object MyTrait {
  final case class EventA(context: Context) extends Event
  // 带Trigger的子类重写方法返回对应值
  final case class EventB(trigger: Trigger) extends Event {
    override def triggerOpt: Option[Trigger] = Some(trigger)
  }
  final case class EventC(trigger: Trigger) extends Event {
    override def triggerOpt: Option[Trigger] = Some(trigger)
  }
  final case class EventD(trigger: Option[Trigger] = None) extends Event {
    override def triggerOpt: Option[Trigger] = trigger
  }
  // 其余不带Trigger的子类无需修改,直接继承默认实现
  final case class EventZ(factor: Factor) extends Event
}

之后直接在原逻辑中调用triggerOpt即可,根据你的业务需求处理无Trigger的场景:

import cats.Monad
// 假设你的for推导使用的效应类型为F(如IO、Either等)
import cats.implicits._

event match {
 case ev @(_: EventA | _: EventB | _: EventC | _: EventD) =>
   val amount = for {
     count1 <- countThis
     count2 <- countThat
     // 有Trigger时调用方法,无Trigger时直接返回成功的空值
     _      <- ev.triggerOpt.fold(Monad[F].unit)(handleSomeTypeOfEvent)
   } yield res + another
 case _ => doSomethingElse()
}

如果不需要兼容cats,也可以手动判断triggerOpt是否为空,对应返回你的效应类型的成功值即可。

方案2:使用独立提取器(无侵入,适合无法修改原有类定义的场景)

如果你不能修改Event及其子类的定义,可以自定义提取器统一提取Trigger:

// 独立定义Trigger提取器,不侵入原有类结构
object TriggerExtractor {
  def unapply(event: Event): Option[Trigger] = event match {
    case EventB(trigger) => Some(trigger)
    case EventC(trigger) => Some(trigger)
    case EventD(Some(trigger)) => Some(trigger)
    case _ => None
  }
}

原有业务逻辑只需增加一行提取Trigger的代码即可:

event match {
 case ev @(_: EventA | _: EventB | _: EventC | _: EventD) =>
   // 用提取器统一获取Trigger
   val triggerOpt = ev match { case TriggerExtractor(t) => Some(t) case _ => None }
   val amount = for {
     count1 <- countThis
     count2 <- countThat
     _      <- triggerOpt.fold(Monad[F].unit)(handleSomeTypeOfEvent)
   } yield res + another
 case _ => doSomethingElse()
}

两种方案都不需要拆分原有的匹配分支,也不需要重复编写for推导逻辑,完全满足需求。


内容的提问来源于stack exchange,提问作者Cypherius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:09:00