我想创建一个
protocol
,对所有符合此enums
的protocol
强制执行某种情况。
例如,如果我有一个像这样的
enum
:
enum Foo{
case bar(baz: String)
case baz(bar: String)
}
我想用
protocol
来扩展它,添加另一种情况:
case Fuzz(Int)
这可能吗?
解决方法是使用
struct
和 static
变量。
注意:这是 Swift 3 中为
Notification.Name
所做的事情
下面是 Swift 3 上的实现
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
,仅当编译时未知值时才使用此方法。
不可以,因为您不能在
case
之外声明 enum
。
extension
可以添加嵌套的enum
,如下所示:
enum Plants {
enum Fruit {
case banana
}
}
extension Plants {
enum Vegetables {
case potato
}
}
这里有一些额外的建议可能会对其他人有所帮助:
用你的例子:
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)
}
}
}
在采用此协议的所有枚举中,我选择强制存在一个静态函数,该静态函数“生成”此情况下有效的内容,并接受此情况作为载体的 Int。因此:
case fuzz(Int)
要在特定枚举中采用和实现这一点,我会写,例如:
protocol HasIntCarryingCase {
static func carryInt(int: Int) -> Self
}
这样,在调用站点,一段代码想要
make这种情况并用它的 Int 填充它,它会简单地调用
enum Foo: HasIntCarryingCase {
case bar(bar: String)
case baz(baz: String)
case fuzz(fuzz: Int)
static func carryInt(int: Int) -> Self { .fuzz(fuzz: int) }
}
,将要携带的 Int 交给它。此调用可以在任何需要 Foo 实例的地方使用,就像实际情况一样:
carryInt
let myIntCarrying: Foo = .carryInt(int: 42)
(不是
func
,而是正常的)从这个特殊的 Int 携带案例中提取 Int。