使用扩展允许您将协议一致性声明保留在实现该协议的方法旁边。
如果没有扩展,想象一下将您的类型声明为:
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
是的,您可以使用(请记住,您可以将这两种技术结合起来)标记您的协议实现,但您仍然会在文件顶部(协议支持声明所在的位置)和文件正文中分开,你的实现在哪里。
此外,请记住,如果您正在实现一个协议,您将在执行过程中从 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
}
}
}
所以你必须在同一个扩展中实现两者。