Swift中遵循含属性要求的协议是否无需显式定义getter与setter?
嘿,这俩问题问到点子上了,正好是Swift协议属性里很容易混淆的点,我给你掰扯清楚:
问题1:在Swift中,创建遵循要求getter和setter的协议的类时,是否无需显式写getter和setter?
完全不需要!Swift里的存储属性(用var声明的那种)本身就自带可读可写的能力,这是它的默认特性。当协议要求某个属性是{ get set }时,你只需要在类/结构体里声明一个普通的var存储属性,就自动满足协议的要求了——因为存储属性天生就有get和set的功能,根本不用你手动写get {}或者set {}的代码块。
举个实际的例子:
// 定义要求可读可写属性的协议 protocol UserProtocol { var name: String { get set } var age: Int { get set } } // 遵循协议的类,直接声明存储属性即可 class User: UserProtocol { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } }
你看,这个User类里的name和age都没写get/set,但编译器完全认可它符合UserProtocol的要求,不会报错。
问题2:未为age定义get/set结构、未为name定义get结构,是不是因为协议里{ get set }的属性仅要求可读可写,存储属性就能满足?
没错,就是这个逻辑!协议里的{ get set }本质是在能力层面做约束:这个属性必须支持读取(get)和修改(set)操作。而Swift的var存储属性天生就具备这两个能力,所以根本不需要额外写getter或setter的实现代码。
反过来想,如果协议要求的是{ get }(只读),那你可以用let常量存储属性,也可以用var存储属性,甚至可以用只写getter的计算属性。但如果是{ get set },就必须用var存储属性,或者是同时实现get和set的计算属性——不过存储属性是最直接省事的方式,因为它默认就达标了。
顺便补个小细节:如果是用计算属性来满足{ get set }的要求,那你才需要显式写get和set的代码块,比如:
class User: UserProtocol { // 私有存储属性做底层存储 private var _name: String // 计算属性显式实现get和set var name: String { get { return _name } set { _name = newValue } } // 存储属性依然不用写get/set var age: Int = 0 init(name: String) { self._name = name } }
这里的name是计算属性,所以必须显式写get和set才能满足协议,但age作为存储属性还是啥都不用加。
内容的提问来源于stack exchange,提问作者JonEF
相关产品推荐
相关产品推荐

