如何避免使用 Swift 2.0 枚举重复自己
How to Don't Repeat Yourself with Swift 2.0 enums
我有多个具有原始值的枚举,但我不喜欢每次从原始值初始化一个时都说 rawValue:
,所以我提供了一个替代的委托初始化器外部标签:
enum E1 : Int {
case One, Two
init?(_ what:Int) {
self.init(rawValue:what)
}
}
enum E2 : Int {
case One, Two
init?(_ what:Int) {
self.init(rawValue:what)
}
}
非常好。我可以说 let e = E1(0)
并且正确的事情发生了。
现在把重复的代码合并一下。我希望 Swift 2.0 协议扩展允许我这样做 - 在 一个 位置编写 init?(_ what:Int)
初始化程序并在 中注入/继承它]both 枚举。但是,我还没有找到可行的方法。问题是协议扩展不知道采纳者将 有 一个 init(rawValue:)
初始化器,我还没有找到让它放心的方法。
我怀疑这是因为 rawValue
初始值设定项存在的自动方式,所以可能什么也做不了。但也许有人有建议。
我能够像这样让它工作:
protocol P {
var rawValue : Int {get}
init?(rawValue: Int)
}
extension P {
init?(_ what:Int) {
self.init(rawValue:what)
}
}
enum E1 : Int, P {
case One, Two
}
enum E2 : Int, P {
case One, Two
}
我们使用常规的 protocol
声明来向协议扩展保证我们的采用者将拥有 init?(rawValue:)
.
[不过,还是有些奇怪的事情发生了。这段代码在我的一个项目中编译,但在另一个项目中不编译。我认为这与其他代码如何使用 P 协议有关;如果没有其他代码使用P协议,一切正常,但是如果其他代码使用P协议,在我没有准确确定的方式下,代码编译失败,神秘关于枚举不符合协议的错误。]
不知道哪里出了问题。最好有孤立的案例。也许更通用的版本有帮助?
protocol BaseRaw {
typealias T
var rawValue : T { get }
init?(rawValue: T)
}
extension BaseRaw {
init?(_ value: T) {
self.init(rawValue: value)
}
}
enum E1 : Int, BaseRaw {
case One = 1
case Two = 2
}
enum E2 : String, BaseRaw {
case One = "1"
case Two = "2"
}
let e = E1(1)
let e2 = E2("2")
print(e) // Optional(E1.One)
print(e!.rawValue) // 1
print(e2) // Optional(E2.Two)
print(e2!.rawValue) // "2"
听起来您想要扩展 RawRepresentable
协议:
extension RawRepresentable {
init?(_ what: RawValue) {
self.init(rawValue: what)
}
}
任何具有原始类型的枚举自动符合 RawRepresentable
,因此您不必使 E1
或 E2
符合任何额外协议:
enum E1: Int {
case One = 1, Two
}
enum E2: String {
case One = "1", Two = "2"
}
let e1 = E1(1) // .One
let e2 = E2("2") // .Two
我有多个具有原始值的枚举,但我不喜欢每次从原始值初始化一个时都说 rawValue:
,所以我提供了一个替代的委托初始化器外部标签:
enum E1 : Int {
case One, Two
init?(_ what:Int) {
self.init(rawValue:what)
}
}
enum E2 : Int {
case One, Two
init?(_ what:Int) {
self.init(rawValue:what)
}
}
非常好。我可以说 let e = E1(0)
并且正确的事情发生了。
现在把重复的代码合并一下。我希望 Swift 2.0 协议扩展允许我这样做 - 在 一个 位置编写 init?(_ what:Int)
初始化程序并在 中注入/继承它]both 枚举。但是,我还没有找到可行的方法。问题是协议扩展不知道采纳者将 有 一个 init(rawValue:)
初始化器,我还没有找到让它放心的方法。
我怀疑这是因为 rawValue
初始值设定项存在的自动方式,所以可能什么也做不了。但也许有人有建议。
我能够像这样让它工作:
protocol P {
var rawValue : Int {get}
init?(rawValue: Int)
}
extension P {
init?(_ what:Int) {
self.init(rawValue:what)
}
}
enum E1 : Int, P {
case One, Two
}
enum E2 : Int, P {
case One, Two
}
我们使用常规的 protocol
声明来向协议扩展保证我们的采用者将拥有 init?(rawValue:)
.
[不过,还是有些奇怪的事情发生了。这段代码在我的一个项目中编译,但在另一个项目中不编译。我认为这与其他代码如何使用 P 协议有关;如果没有其他代码使用P协议,一切正常,但是如果其他代码使用P协议,在我没有准确确定的方式下,代码编译失败,神秘关于枚举不符合协议的错误。]
不知道哪里出了问题。最好有孤立的案例。也许更通用的版本有帮助?
protocol BaseRaw {
typealias T
var rawValue : T { get }
init?(rawValue: T)
}
extension BaseRaw {
init?(_ value: T) {
self.init(rawValue: value)
}
}
enum E1 : Int, BaseRaw {
case One = 1
case Two = 2
}
enum E2 : String, BaseRaw {
case One = "1"
case Two = "2"
}
let e = E1(1)
let e2 = E2("2")
print(e) // Optional(E1.One)
print(e!.rawValue) // 1
print(e2) // Optional(E2.Two)
print(e2!.rawValue) // "2"
听起来您想要扩展 RawRepresentable
协议:
extension RawRepresentable {
init?(_ what: RawValue) {
self.init(rawValue: what)
}
}
任何具有原始类型的枚举自动符合 RawRepresentable
,因此您不必使 E1
或 E2
符合任何额外协议:
enum E1: Int {
case One = 1, Two
}
enum E2: String {
case One = "1", Two = "2"
}
let e1 = E1(1) // .One
let e2 = E2("2") // .Two