Swift:用于枚举的协议不';行不通
对于枚举,我需要的协议定义的一部分是保存一个以“self”作为密钥的字典。这是我第一次尝试:Swift:用于枚举的协议不';行不通,swift,enums,ios8,protocols,Swift,Enums,Ios8,Protocols,对于枚举,我需要的协议定义的一部分是保存一个以“self”作为密钥的字典。这是我第一次尝试: protocol Orderable { // line 1 class var first: Self { get } class var last: Self { get } class var strings: [Self : String] { get } // line 4 } enum Item
protocol Orderable { // line 1
class var first: Self { get }
class var last: Self { get }
class var strings: [Self : String] { get } // line 4
}
enum Item : Int, Orderable {
case ItemA = 0, ItemB, ItemC
static let last : Item = Item.ItemC
var name : String { return Item.strings[self]! }
static let strings: [Item : String] = [
.Item1: "item no. 1", .Item2 : "item no. 2", .Item3: "Item no. 3"
]
}
println ("last item is: \(Item.last.name)") // ==> "last item is: item no. 3"
在第4行失败,错误为:
类型“Self”不符合协议“Hashable”
为了解决这个问题,我尝试从Hashable继承Orderable,如下所示:
protocol Orderable : Hashable { ... }
然而,当我尝试这样做时,游乐场崩溃了
这是解决问题的正确方法吗 操场崩溃的问题不在于你的
Orderable
协议,而在于你的项目
枚举。确实,Orderable
需要实现Hashable
才能工作,但您在操场上看到的问题更多地是由于项目
没有正确实现Orderable
。当代码编写得不正确时,游戏场仍然相当不稳定,所以它对您造成的冲击对我来说并不太奇怪
因此,要解决Xcode 6.0中的编译器错误,您需要执行以下操作:
注意:如果您使用的是Xcode 6.1,请参阅更新
在Orderable
协议中,您已将第一个
、最后一个
和字符串
定义为只读计算属性,但已将它们定义为项
枚举中的读写存储属性。此外,您还忽略了实现第一个属性
而不是定义最后一个,例如:
static let last : Item = Item.ItemC
它需要定义为一个var
,其表达式返回s项。项c
:
static var last : Item { return Item.ItemC }
同样的基本思想可以应用于第一个
和字符串
另外,在字符串
属性中,您使用了.Item1
、.Item2
和.Item3
,而不是.ItemA
、.ItemB
和.ItemC
因此,如果我们解决了所有问题:
protocol Orderable: Hashable {
class var first: Self { get }
class var last: Self { get }
class var strings: [Self : String] { get }
}
enum Item : Int, Orderable {
case ItemA = 0, ItemB, ItemC
static var first: Item { return .ItemA }
static var last : Item { return .ItemC }
static var strings: [Item: String] {
return [
.ItemA: "item no. 1", .ItemB : "item no. 2", .ItemC: "Item no. 3"
]
}
var name : String { return Item.strings[self]! }
}
这与此快速测试配合得很好:
println("last item is: \(Item.last.name)")
println("first item is: \(Item.first.name)")
println("item B is \(Item.strings[Item.ItemB])")
产出:
最后一项是:第3项
第一项是:第1项
B项为可选项(“第2项”)
更新:正如@David在评论中指出的那样,我上面所说的关于在项中实现Orderable
协议属性的内容似乎只是Xcode 6.0中的一个问题。在Xcode 6.1中,以最初的方式实现属性是完全合理的。在Xcode 6.1游乐场中,这可以正常工作:
protocol Orderable: Hashable {
class var first: Self { get }
class var last: Self { get }
class var strings: [Self : String] { get }
}
enum Item : Int, Orderable {
case ItemA = 0, ItemB, ItemC
static var first: Item = .ItemA
static var last : Item = .ItemC
static var strings: [Item: String] = [
.ItemA: "item no. 1", .ItemB : "item no. 2", .ItemC: "Item no. 3"
]
var name : String { return Item.strings[self]! }
}
他的主要问题是,他没有将Orderable声明为Hashable的扩展,而您已经将其作为解决他许多其他问题的副作用进行了修复。协议中的定义classvar-first:Self{get}
只是说协议要求必须有一个get方法。实现上没有任何限制,实际上,您可以使用get和set方法来实现它,尽管6.0编译器似乎有问题。在6.1编译器上,这似乎很好。@David他们在问题中确实说,他们试图将Orderable
声明为Hashable
,我在回答中重申了这一点,所以我认为已经涵盖了这一点。我的观点主要是,由于代码中的其他问题,它无法工作(在他们的例子中,操场正在崩溃)。回复:对属性实现的限制,我没有意识到,谢谢。当时我正在使用6.0编译器,但后来我安装了6.1 GM,我知道你是对的。我将更新答案以反映这一点。是的,我只是想指出,您正在处理一个编译器错误,它的编写方式应该很好。我去掉了很多东西,包括Hashable,把它精简到变量声明和定义的最小值,它仍然在6.0上崩溃。使用一种距离生产就绪还有很长一段路要走的语言(和实现)的荣耀。顺便说一句,也可以将first、last等定义为var
,并使它们也是可变的。虽然实际上分配给它会使操场崩溃…哎呀,我实际上是想在我的编辑中制作那些var
s;谢谢你指出这一点。我还调整了我最初的答案,指出这部分是为了解决编译器错误。也许有一天我们不必在Swift中做太多的变通方法……有些人认为发布未注释的代码而没有文本描述或解释是不好的风格——也就是说,这个答案被标记为低质量
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
enum SimpleEnum : ExampleProtocol {
case enumMember(String)
var simpleDescription: String {
get {
switch self {
case let .enumMember(descript):
return descript
}
}
}
mutating func adjust () {
switch self {
case let .enumMember(desc):
self = .enumMember(desc + " (adjusted)")
}
}
}
var c = SimpleEnum.enumMember("A simple enum.")
var csimpleDescription = c.simpleDescription
c.adjust()
var dsimpleDescription = c.simpleDescription