首先放个简单的Playground作下示范。html
protocol
中属性能够声明为{ get }
或者{ get set }
。大多数人第一眼确定以为{ get }
是约束为 read-only 属性,{ get set }
是约束为 read-write 属性。可是在protocol
中这些约束都是最小约束,也就是说{ get }
属性至少须要是 readable 的,至于它是否 writable 并不做要求;{ get set }
则明确的指出了属性必须是可读写,可是官方文档说明了,用{ get set }
声明的属性,不能在遵照该协议的类型中被实现为let
属性。git
The getter and setter requirements can be satisfied by a conforming type in a variety of ways. If a property declaration includes both the
get
andset
keywords, a conforming type can implement it with a stored variable property or a computed property that is both readable and writeable (that is, one that implements both a getter and a setter). However, that property declaration can’t be implemented as a constant property or a read-only computed property. If a property declaration includes only theget
keyword, it can be implemented as any kind of property. For examples of conforming types that implement the property requirements of a protocol, see Property Requirements.github
给属性设置默认值?这难道不简单?swift
protocol FloatingViewProtocol {
var isDraggable: Bool { get }
}
extension FloatingViewProtocol {
var isDraggable: Bool {
return true
}
}
class FloatingView: FloatingViewProtocol {
var isDraggable = false
}
复制代码
给一个{ get }
属性提供默认值,只须要在extension
中一个return
就搞定,确实很简单,可是这里出现了个问题,在尝试给FloatingView
对象的isAutoAdsorb
属性从新赋值时会报错,提示isDraggable is a get-only property
。ide
因此若是想要从新赋值,则该属性必须是{ get set }
的,可给{ get set }
属性提供默认值也比较尴尬:ui
protocol FloatingViewProtocol {
var isDraggable: Bool { get set }
}
extension FloatingViewProtocol {
var isDraggable: Bool {
get { return true }
set { }
}
}
class FloatingView: FloatingViewProtocol { }
复制代码
如上确实提供了默认值,可是set { }
实在谈不上优雅,而且还有个致命的问题,isDraggable
不是个存储属性。若是FloatingView
在声明时采用了默认的isDraggable
值,那么给FloatingView
对象的isAutoAdsorb
属性从新赋值并不会被保存下来!spa
话说这个时候,咱们是否是该联想一下属性和实例变量的关系 :)code
class FloatingViewProtocolComponent {
var isDraggable = true
public init() {}
}
protocol FloatingViewProtocol {
var component: FloatingViewProtocolComponent { get }
var isDraggable: Bool { get set }
}
extension FloatingViewProtocol {
var isDraggable: Bool {
get { return component.isDraggable }
set { component.isDraggable = newValue }
}
}
class FloatingView: FloatingViewProtocol {
var component = FloatingViewProtocolComponent()
}
复制代码
经过一个component
属性来实现相似实例变量的功能,操做仍是有点骚。component
上面提到苹果文档指明了{ get set }
声明的属性不能被实现为let
。可是由于component
提供了默认值,那么该{ get set }
属性就能够不被实现,同时类能够声明一个同名同类型的let
属性覆盖协议中的属性,就形成了{ get set }
属性能够被声明为let
的假象。orm
{ get }
属性:
{ get set }
属性: