使用擴展允許您保持協議一致性的聲明在實現該協議的方法旁邊。
如果沒有擴展,想象聲明你的類型爲:使用擴展,在那裏你捆綁在一起的協議的執行情況,實現它的這些具體方法
struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {
// lotsa code...
// and here we find the implementation of ArrayLiteralConvertible
/// Create an instance containing `elements`.
init(arrayLiteral elements: T…) {
etc
}
}
進行對比:
struct Queue<T> {
// here go the basics of queue - the essential member variables,
// maybe the enqueue and dequeue methods
}
extension SequenceType {
// here go just the specifics of what you need for a sequence type
typealias Generator = GeneratorOf<T>
func generate() -> Generator {
return GeneratorOf {
// etc.
}
}
}
extension Queue: ArrayLiteralConvertible {
init(arrayLiteral elements: T...) {
// etc.
}
}
是的,你可以用// MARK
來標記你的協議實現(並且記住,你可以結合使用這兩種技術),但是你仍然會被分割到文件的頂部,在那裏協議支持的聲明將會是b e,以及文件的主體,你的實現在哪裏。另外,請記住,如果您正在實施一個協議,您將隨時獲得來自IDE的有用(如果稍爲冗長)反饋,告訴您您還需要執行哪些操作。使用擴展來逐個執行每個協議使它(對我而言)比一次完成所有操作(或者在添加它們時從上到下跳來跳去)要容易得多。
鑑於此,將其他非協議但相關的方法分組爲擴展也很自然。
我實際上偶爾發現它令人沮喪,當你不能做到這一點。例如,
extension Queue: CollectionType {
// amongst other things, subscript get:
subscript(idx: Index) -> T {
// etc
}
}
// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
// this is not valid - you’re redeclaring subscript(Index)
subscript(idx: Int) -> T {
// and this is not valid - you must declare
// a get when you declare a set
set(val) {
// etc
}
}
}
因此,您必須在同一個擴展中實現兩者。
使用你喜歡的任何一個,但擴展使它比單純的'MARK:'更明確,明確指出它開始的位置和結束位置。坦率地說,這不是一個問題,因爲我會同時使用'MARK:'和'extension'。 'extension'的另一個優點是您可以輕鬆地摺疊該代碼(例如「編輯器」 - 「代碼摺疊...」 - 「摺疊」或單擊帶陰影的左邊距)。 – Rob 2015-11-19 22:03:55