2014-09-30 115 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