首先放個簡單的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 }
屬性: