【问题标题】:Is it possible to make an Array extension in Swift that is restricted to one class?是否可以在 Swift 中创建仅限于一个类的 Array 扩展?
【发布时间】:2015-02-05 16:36:47
【问题描述】:

我可以制作一个仅适用于字符串的数组扩展吗?

【问题讨论】:

  • 不确定您的意思 - 您能详细说明您的意图吗?也许是一个例子?
  • @dpassage 您可以通过扩展类遵守协议(developer.apple.com/library/ios/documentation/Swift/Conceptual/…)的要求来扩展事物,我很好奇您是否可以进一步将其限制为仅一个类,以便我的扩展在 Swift 中只适用于字符串数组。
  • 但是描述你想要这样一个扩展做什么。只是功能的问题吗?然后定义一个全局泛型函数。给出一个你希望完成的实际用例。
  • 是的,它只是一个函数。你能描述一下那会是什么样子吗?如果我理解正确,我必须传入数组,这不是最佳的。
  • 它看起来像内置函数。看看find 是如何作用于元素仅是 Equatable 的数组。

标签: arrays swift ios8


【解决方案1】:

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


这在论坛上已经出现过好几次了,答案是否定的,你今天不能这样做,但他们知道这是个问题,他们希望在未来改进它。他们想添加到 stdlib 的东西也需要这个。这就是stdlib有这么多免费功能的原因。它们中的大多数都是针对此问题或“无默认实现”问题(即“traits”或“mixins”)的解决方法。

【讨论】:

  • 谢谢,这似乎是一个奇怪的遗漏。会保持我的手指交叉。
  • 可能想为 2.0 编辑这个,尤其是。就像受骗者所指的那样。
【解决方案2】:

尽管 cmets 中有很多请求,但您仍然没有给出用例,因此很难知道您在追求什么。但是,正如我在评论中已经说过的(并且 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 不是字符串数组,我们一开始就不能将它包装在 StringArrayWrapper 中。

【讨论】:

  • 如果数组可能很大,类可能比结构更好,这样就可以保证传递引用。出于这个原因,我经常将大数组包装在类中 - 这样传递它们就不会涉及复制。
  • Swift 使用写时复制来传递值,因此在大多数情况下,传递大型数组不应该有很大的成本。如果你发现一个主要的成本,你应该打开一个雷达。 Apple 已特别指出,出于性能原因,您不应尝试回避复制。见developer.apple.com/library/ios/documentation/Swift/Conceptual/…底部的注释
  • @RobNapier 这里的属性是var,示例假设它会被写入。
【解决方案3】:

从 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

【讨论】:

  • 您可以将Index == Int 切换为Index: RandomAccessIndexType 并进行一些小的更改,例如startIndex 而不是0endIndex.predecessor()let mid = lo.advancedBy(lo.distanceTo(hi)/2) 加上isEmpty 的提前保释。例如,这意味着它将与 String.UTF16View 一起使用,它是随机访问但不是整数索引。
  • @AirspeedVelocity:完成:)
【解决方案4】:

上面的三位智者已经回答了这个问题 ;-) ,但我谦虚地提供了@Martin 答案的概括。我们可以通过使用仅在我们希望定位的类上实现的“标记”协议来定位任意类。 IE。不必找到协议本身,但可以创建一个简单的协议用于定位所需的类。

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())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 1970-01-01
    • 2010-12-05
    • 2015-01-18
    相关资源
    最近更新 更多