protocol Deck {
var cards: [String] {get set} // {get mutable set}
}

struct MyDeck: Deck {
 var cards: [String] =  (1...7).map {_ in return String(rand())}
}

只是有兴趣我需要在协议(protocol)中指定 {get mutable set} 吗?
如果我的 setter 改变了我的结构,找不到任何关于为什么不在 setter 声明中使用 mutable 关键字的文档

最佳答案

首先注意讨论的关键字是 mutating ,而不是 mutable
set 的默认状态是 mutating

  • 快速回答您的问题:mutating 是 setter 的默认状态,因此您无需明确使用 mutating 关键字来指定它。

  • 细节
    对于 getter 和 setter,以下默认行为成立
  • getnonmutating,默认为
  • setmutating,默认为

  • 因此,指定 ... { get set } 的协议(protocol),例如(在您的示例中),计算属性,期望符合此类协议(protocol)的 nonmutating get 的默认 mutating setstruct
    protocol Deck {
        var cards: [String] {get set}
    }
    
    // implicitly, OK
    struct MyDeckA: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            get { return ["foo"] }
            set { mutateMe += 1 }
        }
    }
    
    // explicitly, OK
    struct MyDeckB: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            nonmutating get { return ["foo"] }
            mutating set { mutateMe += 1 }
        }
    }
    
    /* error, MyDeckC does not conform to Deck
      (mutating getter, wheres a nonmutating one is blueprinted!) */
    struct MyDeckC: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            mutating get { return ["foo"] }
            mutating set { mutateMe += 1 }
        }
    }
    
    如果我们想要一个与上述默认情况不同的 getter 或 setter,我们需要指定这一点(在协议(protocol)中以及明确地说符合此类协议(protocol)的结构)。
    protocol Deck {
        var cards: [String] {mutating get nonmutating set}
    }
    
    /* when conforming to this non-default get/set setup blueprinted in
       protocol Deck, we need to explicitly specify our non-default
       (w.r.t. mutating) getter and setter */
    struct MyDeckD: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            mutating get { mutateMe += 1; return ["foo"] }
            nonmutating set { print("I can't mutate self ...") }
        }
    }
    
    最后,有趣的是,如果我们(对于某些协议(protocol)属性)将一个 setter 蓝图作为默认值( ... {get set} ),即默认为 mutating set ,我们仍然可以通过明确的 nonmutating setter 遵守这样的协议(protocol)
    protocol Deck {
        var cards: [String] {get set}
    }
    
    struct MyDeckE: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            get { return ["foo"] }
            nonmutating set { print("I can't mutate self ...") }
                /* setter cannot mutate self */
        }
    }
    
    我可以假设这是允许的,因为我们让符合协议(protocol)的结构包含一个比蓝图更严格的 setter,关于变异 self 。如果我们为 mutating getter 设计蓝图,自然也是如此:我们仍然可以使用 nonmutating 来遵守这样的协议(protocol)。
    protocol Deck {
        var cards: [String] {mutating get set}
    }
    
    struct MyDeckF: Deck {
        var mutateMe: Int = 0
        var cards: [String] {
            nonmutating get { print("I can't mutate self ..."); return ["foo"] }
                /* getter cannot mutate self */
            set { mutateMe += 1 }
        }
    }
    

    关于Swift 可变设置在属性中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37423595/

    10-11 02:04