Swift:enum的协议不起作用

时间:2014-09-30 16:38:19

标签: swift enums ios8 protocols

我需要一个enum的协议定义的一部分,就是用" 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'不符合协议' Hashable'

为了解决这个问题,我尝试从Hashable继承Orderable,如下所示:

protocol Orderable : Hashable { ...  }

然而,当我尝试时,Playground会崩溃。

这是问题的正确解决方案吗?

2 个答案:

答案 0 :(得分:2)

Playground崩溃的问题不在于您的Orderable协议,而在于Item枚举更多问题。确实Orderable需要实现Hashable才能使其正常工作,但您在Playground中看到的问题更多是由于Item没有正确实现Orderable。当代码编写得不恰当时,游乐场仍然相当不稳定,因此对我而言,它正在崩溃对你来说并不太令人惊讶。

因此,要解决Xcode 6.0中的编译器错误,您需要执行以下操作:

注意:如果您使用的是Xcode 6.1,请参阅更新。

在您的Orderable协议中,您已将firstlaststrings定义为只读计算属性,但您已将其定义为read-在Item枚举中写入存储的属性。此外,您完全忽略了实施first财产。

而不是将last定义为:

static let last : Item = Item.ItemC

需要将其定义为var,其表达式为return s Item.ItemC

static var last : Item { return Item.ItemC }

同样的基本想法可以应用于firststrings

另外,在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])")

输出:

  

最后一项是:项目编号。 3

     

第一项是:项目编号。 1

     

项目B是可选的(“项目编号2”)


更新:正如@David在评论中指出的那样,我上面所说的关于在Orderable中实现Item协议的属性的说法似乎只是一个问题。 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]! }
}

答案 1 :(得分:0)

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