Swift не поддерживает это, потому что Foo
экземпляры нуждаются в сопоставлении с образцом, поскольку они не Equatable
. И единственный разделитель, который допускает многократное сопоставление с шаблоном, это ,
, и этот оператор соответствует операции and
, у вас не может быть or
.
Один уродливый (и я бы сказал, неправильный или вводящий в заблуждение) подход заключается в добавлении соответствия к Equatable
и игнорировании связанных значений:
enum Foo: Equatable {
case a(x: Int)
case b(x: Int)
case c
case d
static func ==(_ lhs: Foo, _ rhs: Foo) -> Bool {
switch (lhs, rhs) {
case (.a, .a): return true
case (.b, .b): return true
case (.c, .c): return true
case (.d, .d): return true
default: return false
}
}
}
Затем вы можете сделать что-то вроде этого:
if [Foo.a(x: 0), Foo.b(x: 0), Foo.c].contains(foo) { ... }
Другой подход - добавить свойство index
и использовать его при тестировании:
enum Foo {
case a(x: Int)
case b(x: Int)
case c
case d
var index: Int {
switch self {
case .a: return 0
case .b: return 1
case .c: return 2
case .d: return 3
}
}
}
И используйте его в соответствии с
if [Foo.a(x: 0), Foo.b(x: 0), Foo.c].map({ $0.index }).contains(foo.index) { ... }
Оба решения более многословны, чем простой переключатель, и они будут выполнимы только в том случае, если вам нужно будет использовать их много раз.
В качестве альтернативы вы можете расширить Array
примерно так:
extension Array where Element == Foo {
func matchesCase(_ foo: Foo) -> Bool {
return contains {
switch ($0, foo) {
case (.a, .a): return true
case (.b, .b): return true
case (.c, .c): return true
case (.d, .d): return true
default: return false
}
}
}
}
, и используйте его так:
if [Foo.a(x: 0), Foo.b(x: 0), Foo.c].matchesCase(foo) { ... }
И четвертое решение :). Добавление функции sameCase
:
enum Foo {
case a(x: Int)
case b(x: Int)
case c
case d
func sameCase(_ foo: Foo) -> Bool {
switch self {
// a little bit more verbose, but don't risk missing new cases
case .a: if case .a = foo { return true } else { return false }
case .b: if case .b = foo { return true } else { return false }
case .c: if case .c = foo { return true } else { return false }
case .d: if case .d = foo { return true } else { return false }
}
}
}
Использование:
if [Foo.a(x: 0), Foo.b(x: 0), Foo.c].contains(where: foo.sameCase) { ... }
// or
if foo.sameCase(.a(x: 0)) || foo.sameCase(.b(x: 0)) || foo.sameCase(.c) { ... }