是否有可能在Swift中创build一个数组扩展?

我可以创build一个适用于(例如)string的数组扩展吗?

从Swift 2开始,现在可以通过协议扩展来实现, 协议扩展提供了符合types的方法和属性实现(可选地受附加约束限制)。

一个简单的例子:为序列元素是String所有符合SequenceTypetypes(例如Array )定义一个方法:

 extension SequenceType where Generator.Element == String { func joined() -> String { return "".join(self) } } let a = ["foo", "bar"].joined() print(a) // foobar 

不能直接为struct Array定义扩展方法,只能针对符合某些协议的所有types(带有可选的约束条件)。 所以人们必须find一个协议Array符合,并提供所有必要的方法。 在上面的例子中,就是SequenceType

另一个例子( 如何在正确的位置插入一个元素到Swift中的sorting数组的变化? ):

 extension CollectionType where Generator.Element : Comparable, Index : RandomAccessIndexType { typealias T = Generator.Element func insertionIndexOf(elem: T) -> Index { var lo = self.startIndex var hi = self.endIndex while lo != hi { // mid = lo + (hi - 1 - lo)/2 let mid = lo.advancedBy(lo.distanceTo(hi.predecessor())/2) if self[mid] < elem { lo = mid + 1 } else if elem < self[mid] { hi = mid } else { return mid // found at position `mid` } } return lo // not found, would be inserted at position `lo` } } let ar = [1, 3, 5, 7] let pos = ar.insertionIndexOf(6) print(pos) // 3 

这里该方法被定义为CollectionType的扩展,因为需要对元素的下标访问,并且元素需要是Comparable

更新:请参阅下面的马丁的答案Swift 2.0更新。 (我不能删除这个答案,因为它被接受;如果Doug能接受Martin的答案,我会删除这个答案以避免将来的混淆。)


这在论坛上已经出现好几次了,答案是否定的,今天你不能这样做,但是他们认为这是一个问题,他们希望将来能够改进。 有些东西他们想添加到stdlib也需要这个。 这就是为什么有这么多的免费function是stdlib。 他们中的大多数都是针对这个问题或“无默认实现”问题(即“特征”或“mixins”)的变通方法。

这已经被上面的三位智者所回答了,但我虚心地提出了@马丁的答案的概括。 我们可以通过使用只在我们希望定位的类上实现的“标记”协议来定位一个任意的类。 IE浏览器。 一个人不需要find一个协议本身,但可以创造一个微不足道的使用目标所需的类。

 protocol TargetType {} extension Array:TargetType {} struct Foo { var name:String } extension CollectionType where Self:TargetType, Generator.Element == Foo { func byName() -> [Foo] { return sort { l, r in l.name < r.name } } } let foos:[Foo] = ["c", "b", "a"].map { s in Foo(name: s) } print(foos.byName()) 

你仍然没有给出一个用例,尽pipe在评论中有很多请求,所以很难知道你在做什么。 但是,正如我已经在评论中所说的(罗布在回答中已经说过),你不会从字面上理解它的。 扩展不能这样工作(目前)。

正如我在评论中所说,我会做的是将数组包装在一个结构。 现在结构保护和保证string的types,我们有封装。 这是一个例子,当然你必须记住,你没有给出你真正想做的事情,所以这可能不是直接令人满意的:

 struct StringArrayWrapper : Printable { private var arr : [String] var description : String { return self.arr.description } init(_ arr:[String]) { self.arr = arr } mutating func upcase() { self.arr = self.arr.map {$0.uppercaseString} } } 

以下是如何调用它:

  let pepboys = ["Manny", "Moe", "Jack"] var saw = StringArrayWrapper(pepboys) saw.upcase() println(saw) 

因此,我们已经有效地将我们的string数组隔离成了一个我们可以用仅适用于string数组的函数来武装它的世界。 如果pepboys不是一个string数组,我们不能将它包装在一个StringArrayWrapper开始。