2014-09-30 109 views
1

我需要一個枚舉的協議定義的一部分是將一個以「self」作爲關鍵字的字典。所以這是我第一次嘗試:Swift:枚舉協議不起作用

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行出現錯誤:

型「自我」不符合協議「哈希的」

爲了解決這個問題,我試圖從Hashable繼承Orderable,如下所示:

protocol Orderable : Hashable { ... } 

但是,當我嘗試該操作時,Playground崩潰。

這是問題的正確解決方案嗎?

回答

2

操作系統崩潰的問題與Orderable協議沒有太大的關係,但更多與您的Item枚舉相關。的確,Orderable需要執行Hashable才能正常工作,但是您在Playground中看到的問題更多的是由於Item未正確執行Orderable。當代碼寫得不對時,遊樂場還是相當不穩定的,所以對我來說它並沒有讓你感到驚訝。

因此,要解決該編譯器的bug在Xcode 6.0,你需要做到以下幾點:

注:如果您使用的Xcode 6.1,看到更新。

在你Orderable協議,您已經定義firstlast,並strings爲只讀屬性計算的,但你將它們定義爲讀寫存儲在Item枚舉屬性。另外,你忽略了完全實現你的first屬性。

而不是定義last,例如,作爲:

static let last : Item = Item.ItemC 

它需要與表達被定義爲varreturn小號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])") 

輸出:

last item is: Item no. 3

first item is: item no. 1

item B is Optional("item no. 2")


更新:正如@David在評論中指出的那樣,我上面關於在Item中實現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]! } 
} 
+0

他的主要問題是,他不作爲擴展可哈希的,您已固定爲固定了很多的副作用聲明可訂購他有其他問題。協議中定義'class var first:Self {get}'只是說協議要求必須有get方法。對實現沒有任何限制,實際上可以使用get和set方法來實現它,儘管6.0編譯器似乎有問題。在6.1編譯器上看起來很好。 – 2014-09-30 20:35:13

+0

@David他們在問題中表示他們試圖將'Orderable'聲明爲'Hashable',並且在我的回答中重申了這一點,所以我認爲這已經涵蓋了。我的觀點主要是因爲他們的代碼中存在其他問題,所以它沒有工作(在他們的案例中,遊樂場正在崩潰)。 Re:對屬性實現的限制,我沒有意識到,謝謝。我當時使用的是6.0編譯器,但自從安裝了6.1版本的GM之後,我發現你是正確的。我會更新答案以反映這一點。 – 2014-09-30 20:46:21

+0

是的,我只是想指出你正在解決一個編譯器錯誤,它應該沒問題。我花了很多東西,包括Hashable,把它分解爲變量聲明和定義的最小值,它仍然在6.0上崩潰。與語言(和實現)一起工作的榮耀,從生產就緒方面來說還有很長的路要走。 – 2014-09-30 20:52:19

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 
+2

某些人發佈未註釋的代碼而沒有文字說明或解釋 - 這種回答被標記爲低質量 – 2015-06-01 18:35:04