Arrays 是否可以在Swift中创建一个仅限于一个类的数组扩展?
我可以做一个数组扩展,例如只应用于字符串吗?更新:请参阅下面Martin的答案,了解Swift 2.0更新。(我不能删除此答案,因为它已被接受;如果道格可以接受马丁的答案,我将删除此答案以避免将来的混淆。)Arrays 是否可以在Swift中创建一个仅限于一个类的数组扩展?,arrays,swift,ios8,Arrays,Swift,Ios8,我可以做一个数组扩展,例如只应用于字符串吗?更新:请参阅下面Martin的答案,了解Swift 2.0更新。(我不能删除此答案,因为它已被接受;如果道格可以接受马丁的答案,我将删除此答案以避免将来的混淆。) 这在论坛上已经出现过好几次了,答案是不,你今天不能这样做,但是他们知道这是一个问题,他们希望在将来改进这一点。他们希望向stdlib中添加的某些内容也需要这样做。这就是为什么有这么多免费函数是stdlib。大多数都是解决这个问题或“无默认实现”问题(即“traits”或“mixin”)的解
这在论坛上已经出现过好几次了,答案是不,你今天不能这样做,但是他们知道这是一个问题,他们希望在将来改进这一点。他们希望向stdlib中添加的某些内容也需要这样做。这就是为什么有这么多免费函数是stdlib。大多数都是解决这个问题或“无默认实现”问题(即“traits”或“mixin”)的解决方案。尽管在注释中有许多请求,但您仍然没有给出用例,因此很难知道您要的是什么。但是,正如我在评论中已经说过的(Rob在回答中也说过),你不会从字面上理解它;扩展不是那样工作的(目前) 正如我在评论中所说,我要做的是将数组包装在一个结构中。现在,结构保护并保证字符串的类型,我们进行了封装。这里有一个例子,当然你必须记住,你没有给出你真正想做的事情的指示,所以这可能不是直接令人满意的:
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不是一个字符串数组,我们就不能从一开始就将其包装在StringArrayRapper中。从Swift 2开始,这可以通过协议扩展来实现, 为一致性类型提供方法和属性实现 (可选地受到附加约束的限制) 一个简单的例子:为所有类型定义一个方法 到
SequenceType
(例如Array
),其中sequence元素是字符串
:
extension SequenceType where Generator.Element == String {
func joined() -> String {
return "".join(self)
}
}
let a = ["foo", "bar"].joined()
print(a) // foobar
不能直接为struct Array
定义扩展方法,只能为所有类型定义扩展方法
符合某些协议(带有可选约束)。这么一个
必须找到Array
符合的协议,并提供所有必要的方法。在上面的示例中,即SequenceType
另一个示例(的变体):
扩展集合类型,其中生成器。元素:可比较,索引:RandomAccessIndexType{
typealias T=生成器.Element
func insertionIndexOf(elem:T)->索引{
var lo=自启动索引
var hi=self.endIndex
你好{
//中=低+(高-1-低)/2
让mid=lo.advancedBy(lo.distanceTo(hi.PRESIONER())/2)
如果self[mid]CollectionType
的扩展,因为
需要对元素进行下标访问,并且元素是
要求具有可比性这一点已经得到了上述三位智者的回答;-),但我谦恭地概括了@Martin的答案。我们可以通过使用“标记”协议来定位任意类,该协议只在我们希望定位的类上实现。也就是说,我们不需要找到一个协议本身,但可以创建一个简单的协议,用于针对所需的类
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())
协议目标类型{}
扩展数组:TargetType{}
结构Foo{
变量名称:String
}
扩展集合类型,其中Self:TargetType,Generator.Element==Foo{
func byName()->[Foo]{返回排序{l,r在l.name
不确定您的意思-您能详细说明您的意图吗?也许是一个例子?@dpassage您可以根据扩展类遵守协议()的要求进行扩展,我很好奇您是否可以进一步将其限制为仅限于一个类,以便我在Swift中的扩展仅适用于字符串数组。但请描述您希望这种扩展做什么。这只是一个函数的问题吗?然后定义一个全局泛型函数。给出一个你希望实现的实际用例。是的,它只是一个函数。你能描述一下那会是什么样子吗?如果我理解正确,我必须传入数组,这不是最优的。它看起来像内置函数。看看find
在元素只能相等的数组上是如何工作的。谢谢,这看起来确实有点奇怪。我会祈求好运的。可能想在2.0版中编辑这个,特别是当重复引用它时。如果数组可能很大,则类可能比结构更好,这样可以保证通过引用传递。出于这个原因,我经常将大数组包装在类中,这样传递它们就不需要复制。Swift使用“写时拷贝”作为传递值,因此在大多数情况下传递大数组不会产生太大的成本。如果你发现一个主要的成本,你应该打开一个雷达。苹果公司特别指出,你不应该因为性能原因而回避复制。请参见@RobNapier底部的注释此处的属性是一个var
,示例假设它将被写入。您可以将Index==Int
切换到Index:RandomAccessIndexType
,并进行一些小的更改,例如startIndex
而不是0
,endIndex.preference()
,让mid=lo.advancedBy(lo.distanceTo(hi)/2)
加上提前保释是空的
。例如,这意味着它将与
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())