Добавление случая к существующему перечислению с протоколом
Я хочу создать protocol
, который накладывает определенный случай на все enums
, соответствующие этому protocol
.
Например, если у меня есть enum
, как это:
enum Foo{
case bar(baz: String)
case baz(bar: String)
}
Я хочу расширить его с помощью protocol
, который добавит еще один случай:
case Fuzz(Int)
Возможно ли это?
Ответы
Ответ 1
Дизайн
Обходной задачей является использование переменных struct
с static
.
Примечание. Это делается в Swift 3 для Notification.Name
Ниже приведена реализация в Swift 3
Struct:
struct Car : RawRepresentable, Equatable, Hashable, Comparable {
typealias RawValue = String
var rawValue: String
static let Red = Car(rawValue: "Red")
static let Blue = Car(rawValue: "Blue")
//MARK: Hashable
var hashValue: Int {
return rawValue.hashValue
}
//MARK: Comparable
public static func <(lhs: Car, rhs: Car) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}
Протокол
protocol CoolCar {
}
extension CoolCar {
static var Yellow : Car {
return Car(rawValue: "Yellow")
}
}
extension Car : CoolCar {
}
Вызов
let c1 = Car.Red
switch c1 {
case Car.Red:
print("Car is red")
case Car.Blue:
print("Car is blue")
case Car.Yellow:
print("Car is yellow")
default:
print("Car is some other color")
}
if c1 == Car.Red {
print("Equal")
}
if Car.Red > Car.Blue {
print("Red is greater than Blue")
}
Примечание:
Обратите внимание, что этот подход не является заменой enum
, используйте это, только когда значения не известны во время компиляции.
Ответ 2
нет, так как вы не можете объявить case
вне enum
.
Ответ 3
An extension
может добавить вложенный enum
, например:
enum Plants {
enum Fruit {
case banana
}
}
extension Plants {
enum Vegetables {
case potato
}
}
Ответ 4
Вот пара дополнительных выплат, которые могут помочь кому-то:
Используя ваш пример:
enum Foo {
case bar(baz: String)
case baz(bar: String)
}
Вы можете считать, что он "вложен" в case
вашего собственного enum
:
enum FooExtended {
case foo(Foo) // <-- Here will live your instances of `Foo`
case fuzz(Int)
}
С помощью этого решения становится более трудоемким доступ к "скрытым" случаям, связанным с типом. Но это упрощение может быть полезным в некоторых приложениях.
Другая альтернатива проходит путем просто воссоздания и расширения ее, имея способ конвертировать Foo
в расширенный enum
FooExtended
(например, с пользовательским init
):
enum FooExtended {
case bar(baz: String)
case baz(bar: String)
case fuzz(Int)
init(withFoo foo: Foo) {
switch foo {
case .bar(let baz):
self = .bar(baz: baz)
case .baz(let bar):
self = .baz(bar: bar)
}
}
}
Там может быть много мест, где один, другой или оба этих решения не имеют абсолютно никакого смысла, но я уверен, что они могут быть полезны кому-то там (даже если это упражнение).