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

如何在Scala中实现支持位运算的抽象Flagged枚举

Scala 实现通用带位运算的Flagged枚举方案

要解决位运算返回类型不匹配、避免重复实现的问题,可以利用Scala 3的泛型或特质+工厂方法机制,实现抽象的Flagged枚举基类,确保位运算返回具体的枚举子类类型。

方案一:泛型特质 + 子类工厂方法

通过泛型特质定义通用位运算逻辑,每个枚举子类实现专属的实例构造方法,保证位运算返回正确的子类类型:

trait FlaggedEnum[T <: FlaggedEnum[T]] {
  val value: Long
  // 子类必须实现的工厂方法,用于构造同类型实例
  protected def create(value: Long): T

  def |(other: T): T = create(value | other.value)
  def &(other: T): T = create(value & other.value)
  def ^(other: T): T = create(value ^ other.value)
  def unary_~ : T = create(~value)
  def hasFlag(flag: T): Boolean = (value & flag.value) == flag.value
}

// 具体权限枚举实现
sealed case class Permissions(override val value: Long) extends FlaggedEnum[Permissions] {
  override protected def create(value: Long): Permissions = Permissions(value)
}

object Permissions {
  val Write = Permissions(1 << 0)
  val Read = Permissions(1 << 1)
  val Execute = Permissions(1 << 2)
}

@main def testPermissions(): Unit = {
  val combined = Permissions.Write | Permissions.Read
  println(combined) // 输出 Permissions(3)
  println(combined.hasFlag(Permissions.Read)) // 输出 true
  println(combined & Permissions.Write) // 输出 Permissions(1)
}

方案二:自类型约束 + 工厂对象

如果想进一步减少子类重复代码,可结合自类型约束和工厂对象,通过反射简化实例构造:

trait FlaggedEnum {
  self: Product =>
  val value: Long

  def |(other: self.type): self.type = {
    val newValue = value | other.value
    // 通过调用枚举伴生对象的apply方法构造实例
    self.getClass.getDeclaredMethod("apply", classOf[Long])
      .invoke(null, newValue.asInstanceOf[AnyRef])
      .asInstanceOf[self.type]
  }

  def hasFlag(flag: self.type): Boolean = (value & flag.value) == flag.value
  // 同理可实现&、^等其他位运算
}

// Scala 3枚举实现
enum Permissions(val value: Long) extends FlaggedEnum {
  case Write extends Permissions(1 << 0)
  case Read extends Permissions(1 << 1)

  // 伴生对象提供工厂方法,处理单个标志和组合标志
  def apply(value: Long): Permissions = value match {
    case Write.value => Write
    case Read.value => Read
    case combined => new Permissions(combined) {} // 生成组合值实例
  }
}

@main def test(): Unit = {
  val combined = Permissions.Write | Permissions.Read
  println(combined.value) // 输出3
  println(combined.hasFlag(Permissions.Read)) // 输出true
}

核心要点

  • 泛型方案类型更安全,无需反射,适合大多数业务场景;
  • 反射方案能减少重复代码,但需要确保每个枚举都提供对应的工厂方法;
  • 位运算的返回类型必须绑定到具体子类,避免类型转换,保证代码简洁性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:05:26