假设有一个泛型方法声明,它根据指定的模式执行一组操作,如下所示:
def doSomethingSmart(mode: OpMode, someGoodyList: List[Any]): Boolean = { /* do foo */ }
其中OpMode是由以下各项组成的类型/枚举:
将两者放在一起显然会产生单模式,可重复使用的代码块。
现在,类型/枚举部分可能看起来像这样:
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()时提供内联构造
答案 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的枚举类型。