Swift可变属性设置

Sha*_*fax 3 swift

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

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

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

dfr*_*fri 8

首先请注意,讨论关键字mutating不是mutable


的默认状态setmutating

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

细节

对于getter和setter,以下默认行为适用

  • getnonmutating按默认
  • setmutating按默认

因此,指定的协议... { get set },比如说(如在你的例子),一个计算属性,期望的默认nonmutating getmutating 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 }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们想要一个不同于上面默认情况的getter或setter,我们需要指定它(在协议中,以及明确地说符合该协议的结构中)。

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 ...") }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,有趣的是,如果我们(对于某些协议属性)将设置程序蓝图设置为默认值(... {get set}),即默认设置为mutating set,则我们仍可以使用显式nonmutating设置程序来遵守此类协议

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 */
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以假定这是允许的,因为在变异方面,我们让符合协议的结构包含一个设置器该设置器比蓝图更严格self。如果我们对mutating吸气剂进行蓝图,自然也是如此:我们可能仍然会遵循这样的协议nonmutating

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 }
    }
}
Run Code Online (Sandbox Code Playgroud)