Scala类似于方法的参数

时间:2013-08-15 22:34:28

标签: scala arguments bit-manipulation

假设有一个泛型方法声明,它根据指定的模式执行一组操作,如下所示:

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

其中OpMode是由以下各项组成的类型/枚举:

  1. 创建
  2. 删除
  3. 修改
  4. 无论
  5. 将两者放在一起显然会产生单模式,可重复使用的代码块。

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

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

    但是,假设您希望扩展doSomethingSmart()的范围,以跨越通常使用按位运算符完成的操作,例如:Create&修改&随你。是否存在将位掩码参数限制为该有限数据集(即枚举/类型)的“scala-way”。也许是这些方面的东西:

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

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

    TIA。

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

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

1 个答案:

答案 0 :(得分: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可以使用更接近您希望的用途。

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