Swift 实现枚举ForwardIndexType
我一直在努力为枚举正确地实现Swift 实现枚举ForwardIndexType,swift,enums,Swift,Enums,我一直在努力为枚举正确地实现ForwardIndexType协议,特别是在处理结束情况(即最后一项没有后续项)时。Swift语言手册并未真正涵盖该协议 下面是一个简单的例子 enum ThreeWords : Int, ForwardIndexType { case one=1, two, three func successor() ->ThreeWords { return ThreeWords(rawValue:self.rawValue +
ForwardIndexType
协议,特别是在处理结束情况(即最后一项没有后续项)时。Swift语言手册并未真正涵盖该协议
下面是一个简单的例子
enum ThreeWords : Int, ForwardIndexType {
case one=1, two, three
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1)!
}
}
succession()
函数将返回下一个枚举数值,但最后一个元素除外,该元素将因异常而失败,因为之后没有值。三个
ForwardTypeProtocol
不允许succession()
返回条件值,因此似乎无法发出没有后继者的信号
现在,在for循环中使用它来迭代枚举的所有可能值的闭合范围,最终情况会遇到问题:
for word in ThreeWords.one...ThreeWords.three {
print(" \(word.rawValue)")
}
println()
//Crashes with the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
在执行for循环中的语句之前,Swift莫名其妙地调用范围结束值的succession()
函数。如果范围半开ThreeWords.one..实际上,似乎最后一个值将调用后续值
enum ThreeWords : Int, ForwardIndexType {
case one=1, two, three
case EXHAUST
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1) ?? ThreeWords.EXHAUST
}
}
您可能希望这样做,但为了解决这个问题,您可以简单地添加一个sentinel值作为后续值。似乎,..
操作符
func ...<Pos : ForwardIndexType>(minimum: Pos, maximum: Pos) -> Range<Pos>
因此,如果要将enum
用作Range.Index
,则必须定义最后一个值的下一个
enum ThreeWords : Int, ForwardIndexType {
case one=1, two, three
case EXHAUST
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1) ?? ThreeWords.EXHAUST
}
}
这是一个老问题,但我想总结一些事情,并发布另一个可能的解决方案
正如@jtbandes和@rintaro已经声明的那样,用start…end
操作符创建的闭合范围是用start.在内部创建的,这很糟糕,因为现在我所有的enum switch语句都感染了一个必需的默认情况
enum ThreeWords : Int, ForwardIndexType {
case one=1, two, three
case EXHAUST
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1) ?? ThreeWords.EXHAUST
}
}
for word in ThreeWords.one...ThreeWords.three {...}
var interval:ClosedInterval = ThreeWords.one...ThreeWords.four
enum ThreeWords : Int, ForwardIndexType, Comparable {
case one=1, two, three, four
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1)!
}
}
func <<T: RawRepresentable where T.RawValue: Comparable>(lhs: T, rhs: T) -> Bool {
return lhs.rawValue < rhs.rawValue
}
var interval:ClosedInterval = ThreeWords.one...ThreeWords.four
switch(ThreeWords.four) {
case ThreeWords.one...ThreeWords.two:
print("contains one or two")
case let word where interval ~= word:
print("contains: \(word) with raw value: \(word.rawValue)")
default:
print("no case")
}