我可以制作适用于例如Strings的数组扩展吗?
答案 0 :(得分:13)
从Swift 2开始,现在可以使用协议扩展来实现, 它为符合类型提供方法和属性实现 (可选择受其他约束限制)。
一个简单的例子:为所有符合要求的类型定义一个方法
至SequenceType
(例如Array
),其中序列元素为String
:
extension SequenceType where Generator.Element == String {
func joined() -> String {
return "".join(self)
}
}
let a = ["foo", "bar"].joined()
print(a) // foobar
无法直接为struct Array
定义扩展方法,但仅适用于所有类型
符合某些协议(带有可选约束)。所以一个
必须找到Array
符合的协议,并提供所有必要的方法。在上面的示例中,即SequenceType
。
另一个例子(How do I insert an element at the correct position into a sorted array in Swift?的变体):
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
。
答案 1 :(得分:5)
更新:请参阅下面的Martin对Swift 2.0更新的回答。 (我不能删除这个答案,因为它被接受;如果Doug能接受Martin的答案,我会删除这个答案以避免将来混淆。)
这已在论坛上多次出现,答案是否定的,你今天不能这样做,但他们认为这是一个问题,他们希望将来能够改善这一点。他们想要添加到stdlib的东西也需要这个。这就是stdlib有这么多免费功能的原因。其中大多数是解决这个问题或“无默认实现”问题(即“特征”或“混合”)的解决方法。
答案 2 :(得分:0)
尽管评论中有很多请求,但你还没有给出一个用例,所以很难知道你在追求什么。但是,正如我在评论中已经说过的那样(罗布在答案中说过),你不会从字面上理解它;扩展不会那样(目前)。
正如我在评论中所说,我要做的是将数组包装在一个结构中。现在结构保护并保证字符串的类型,我们有封装。这是一个例子,当然你必须记住,你没有表明你真正想做的事情,所以这可能不会直接令人满意:
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)
因此,我们有效地将字符串数组隔离到一个我们可以使用仅适用于字符串数组的函数来支持它的世界。如果pepboys
不是字符串数组,我们就无法将它包装在StringArrayWrapper中开始。