例如,我有一组选项可以传递给某些流程,例如
struct Options: OptionSet {
let rawValue: Int
static let floogled = Options(rawValue: 1 << 0)
static let jibjabbed = Options(rawValue: 1 << 1)
}
这些被传递给某些功能,例如foo(options: .floogled)
和bar(options: .jibjabbed)
。
现在,通常当我调用这些函数时,意图是启用所有选项。因此,我可以使用默认值定义函数,例如
func foo(options: Options = [.floogled, .jibjabbed]) {
...
}
,依此类推,然后只需调用foo()
。到目前为止一切顺利。
但是,在特殊情况下,我不想在启用所有选项的情况下调用这些函数,如果我可以指定要启用 not 的选项,则用法会更加直观比哪些选项保持启用状态。例如,我想打电话给foo(options: .notFloogled)
而不是foo(options: .jibjabbed)
。
我可以想到两种方法来做到这一点。第一种方法是更改选项集的定义,以便否定地定义其成员。换句话说
struct OptionsAlternative: OptionSet {
let rawValue: Int
static let notFloogled = Options(rawValue: 1 << 0)
static let notJibjabbed = Options(rawValue: 1 << 1)
}
然后将在默认情况下在不禁用任何选项的情况下定义功能;即
func foo(options: OptionsAlternative = []) {
...
}
对于默认行为,我可以像foo()
那样称呼它,而当我需要禁用特定选项时,可以像foo(options: .notFloogled)
这样称呼它。但是,我不想这样做,因为这会使函数的实现变得不直观。我必须以双重否定的方式实现考虑了这些选项的部分。比较这是多么笨拙:
if !options.contains(.notFloogled) {
// Floogling is enabled. Floogle the foo.
...
}
相对
if options.contains(.floogled) {
// Floogling is enabled. Floogle the foo.
...
}
第二种方法是包括成员以指示选项的存在,如在原始解决方案中一样,以及便利成员用于指示选项的不存在。即
extension Options {
/// Not floogled; only jibjabbed.
static let notFloogled: Options = [.jibjabbed]
/// Not jibjabbed; only floogled.
static let notJibjabbed: Options = [.floogled]
}
但是,如果我要禁用多个选项(这可能是首先使用选项集的主要原因,这是不可行的),则无法使用。例如,如果我现在叫foo(options: [.notFloogled, .notJibjabbed])
,则会得到一个启用了 both 浮动和短刺的选项集,而不是 都不是。
在保持实现和用法尽可能直观的同时,还有另一种方法可以实现我想要实现的目标吗?
答案 0 :(得分:3)
OptionSet是一个 set 。它有一个代数(SetAlgebra)。因此,您不需要“反向选项”; you 反转。要进行反演,只需自己从“全部”情况中减去。
要进行说明(使用Apple自己的OptionSet示例):
struct ShippingOptions: OptionSet {
let rawValue: Int
static let nextDay = ShippingOptions(rawValue: 1 << 0)
static let secondDay = ShippingOptions(rawValue: 1 << 1)
static let priority = ShippingOptions(rawValue: 1 << 2)
static let standard = ShippingOptions(rawValue: 1 << 3)
// include common combinations, including an all case
static let express: ShippingOptions = [.nextDay, .secondDay]
static let all: ShippingOptions = [.express, .priority, .standard]
}
// now form the desired options using subtractions
let negatives : ShippingOptions = [.standard] // the ones you _don't_ want
let opts = ShippingOptions.all.subtracting(negatives) // subtract them from "all"!
// and pass `opts`
答案 1 :(得分:0)
这有点令人困惑。那么,这些选项是否互相排斥?因为您的补语.notFloogled
说是.jibjiabbed
(在最后一个示例中)。但是在顶部,您可以同时启用这两个选项。更复杂的是,如果结构中同时包含变量.floogled
和.notFloogled
,则可以将两个变量都添加到foo()
的array参数中,然后处理哪个选项。 / p>
要解决补码问题:
我猜原始值说明了在二进制代码中启用哪个选项。
因此,我假设1表示启用,0表示不执行任何操作。
在对.notFloogled
使用补码的情况下,我将重新解释二进制代码,并说1 isnotEnable和0不执行任何操作。否则,如果您说notFloggled被取消,那么您就已经提到了问题。因此,您需要重新解释才能不启用特定选项。当您不知道如何处理选项时,很难提出建议。
尽管如此,我可能会做类似的事情
struct Options: OptionSet {
let rawValue: Int
static let floogled = Options(rawValue: 1 << 0)
static let jibjabbed = Options(rawValue: 1 << 1)
}
enum OptionsComplement {
case notFloogled
case notJibjabbed
}
func foo(options: Options = [.floogled, .jibjabbed]) {
...
}
func foo(options: [OptionsComplement] = []) {
var optionsEnabled: Options = []() //whatever type the array is
if !options.contains(.notFloggled) {
optionsEnabled.append(.floogled)
}
if !options.contains(.notJibjabbed) {
optionsEnabled.append(.jibjabbed)
}
foo(options: optionsEnabled)
}
答案 2 :(得分:-1)
我想,如果我知道,我将总是通过否定样式的选项(notFloogled
/ notJibjabbed
),仅以肯定的方式阅读,我可以:
struct Options: OptionSet {
let rawValue: Int
static let notFloogled = Options(rawValue: 1 << 0)
static let notJibjabbed = Options(rawValue: 1 << 1)
}
extension Options {
var isFloogled: Bool {
return !self.contains(.notFloogled)
}
var isJibjabbed: Bool {
return !self.contains(.notJibjabbed)
}
}
func foo(options: Options = []) {
if options.isFloogled {
// Floogle the foo
}
...
}
foo() // With all options enabled
foo(options: .notFloogled) // With floogling disabled
foo(options: [.notFloogled, .notJibjabbed]) // With floogling jibjabbing disabled