0

假设有一个通用方法声明,它基于指定模式执行一组操作,如下所示:

def doSomethingSmart(mode: OpMode, someGoodyList: List[Any]): Boolean = { /* do foo */ }

其中 OpMode 是一个类型/枚举,包括:

  1. 创造
  2. 删除
  3. 调整
  4. 任何

将两者放在一起显然会产生一个单模式、可重用的代码块。

现在,类型/枚举部分可能看起来像这样:

object OpMode extends Enumeration {
  type OpMode = Value
  val Read, Write, Create, Modify, Delete, Whatever = Value
}

但是,假设您想扩展 doSomethingSmart() 的范围以涵盖通常使用按位运算符完成的工作,例如:Create & Modify & What。是否存在将位掩码参数限制为该有限数据集(即枚举/类型)的“scala 方式”。也许是这样的:

def doSomethingSmarter(more: T < [BitwiseSelectionOf[OpMode]], ...

或者,最好简单地退回到二进制索引值分配 - 在这种情况下,本身没有“类型”检查?

TIA。

编辑:我想另一种可能性是将 OpMode 更改为 List ,然后运行一系列“包含”操作。

编辑 2:特别是,我正在寻找一种有效的机制,在调用 doSomethingSmarter() 时提供内联结构

4

1 回答 1

0

枚举定义了一个名为 ValueSet 的内部类型,它至少为您提供了一些您正在寻找的功能。它上面的方法仍然类似于 Set(您可以使用 添加新模式+,并使用 检查模式contains),但它可能符合您的目的。

编辑:有一些有趣的摆弄并想出了这个:

import scala.collection.BitSet

object OpMode extends Enumeration {

  protected case class Val(name: String, val mask: Int) extends super.Val(nextId, name)

  type OpMode = Val

  val Read = Val("Read", 1)
  val Write = Val("Write", 2)
  val Create = Val("Create", 4)
  val Modify = Val("Modify", 8)
  val Delete = Val("Delete", 16)
  val Whatever = Val("Whatever", 32)

  case class FlagSet(bits: BitSet) {
    def isSet(mode: OpMode) = bits.contains(mode.mask)
    def +(mode: OpMode) = new FlagSet(bits + mode.mask)
    def -(mode: OpMode) = new FlagSet(bits - mode.mask)
    def &(other: FlagSet) = new FlagSet(bits & other.bits)
    def &~(other: FlagSet) = new FlagSet(bits &~ other.bits)
    def ^(other: FlagSet) = new FlagSet(bits ^ other.bits)
    def |(other: FlagSet) = new FlagSet(bits | other.bits)
    def size = bits.size
    // etc.

  }

  object FlagSet {
    def apply(flags: OpMode*): FlagSet = apply(BitSet(flags.map(_.mask):_*))
    def apply(modes: ValueSet): FlagSet = apply(BitSet(modes.toSeq.map{ case m: OpMode => m.mask }:_*))
  }

}

def doSomethingSmarter(modes: OpMode.FlagSet, someGoodyList: List[Any]) = modes.size

val flags = OpMode.FlagSet(OpMode.Read, OpMode.Write)

doSomethingSmarter(flags, Nil)

val modes = OpMode.ValueSet(OpMode.Read, OpMode.Write)

doSomethingSmarter(OpMode.FlagSet(modes), Nil)

基本上,我扩展了 Enumeration.Val 类型,为每种模式添加了合适的位掩码,并添加了一个内部类FlagSet以在 OpModes 和底层 BitSet 之间进行互操作。更改 doSomethingSmarter 以采用这样的 FlagSet 可以使使用更接近您的期望。

以上可能可以改进,但使用枚举可能会很棘手。作为替代方案,您可能会发现使用密封特征和扩展它的案例类/对象更可取 - 这通常可以使语义更接近 Java 枚举类型的可能。

于 2013-08-15T23:35:26.760 回答