我需要的枚举协议(protocol)定义的一部分是保存一个以“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 : 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”不符合协议(protocol)“Hashable”
为了解决这个问题,我尝试从 Hashable 继承 Orderable,如下所示:
protocol Orderable : Hashable { ... }
但是,当我尝试这样做时,Playground 崩溃了。
这是解决问题的正确方法吗?
最佳答案
Playground 崩溃的问题不在于您的 Orderable
协议(protocol),而在于您的 Item
枚举。 Orderable
确实需要实现 Hashable
才能正常工作,但是您在 Playground 中看到的问题更多是由于 Item
未正确实现 Orderable
。当代码编写得不正确时,Playgrounds 仍然相当不稳定,所以我对它崩溃并不感到惊讶。
因此,要解决 Xcode 6.0 中的编译器错误,您需要执行以下操作:
注意:如果您使用的是 Xcode 6.1,请参阅更新。
在您的Orderable
协议(protocol)中,您已将first
、last
和strings
定义为只读计算属性,但您已将它们定义为 Item
枚举中的读写存储属性。此外,您还完全忽略了实现 first
属性。
而不是定义last
,例如:
static let last : Item = Item.ItemC
它需要被定义为一个var
,带有一个返回
Item.ItemC
的表达式:
static var last : Item { return Item.ItemC }
同样的基本思想可以应用于first
和strings
。
此外,在您的 strings
属性中,您使用了 .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])")
输出:
last item is: Item no. 3
first item is: item no. 1
item B is Optional("item no. 2")
更新:正如@David 在评论中指出的,我上面所说的关于仅在 Item
中实现 Orderable
协议(protocol)的属性似乎是 Xcode 6.0 中的一个问题。在 Xcode 6.1 中,按照您原来的方式实现属性是完全合理的。在 Xcode 6.1 Playground 上,这工作正常:
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]! }
}
关于Swift:枚举协议(protocol)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26125863/