【问题标题】:Pass Array containing either class or struct传递包含类或结构的数组
【发布时间】:2015-01-31 18:33:21
【问题描述】:

在 Swift 中,我声明了一个与 Array.count 不同的函数,仅在于如果 array == nil 函数返回 0。这与我的UITableViewDataSource 有关,但这在这里并不重要。问题是,如果我将函数声明为:

class func countOfItemsInArray(array: [AnyObject]?) -> Int

然后尝试向它传递一个结构数组,它声明数组中的结构不符合AnyObject。我理解为什么会这样(我认为),但有没有办法让类 结构能够实现这一点,还是我应该放弃复制和粘贴?

【问题讨论】:

    标签: arrays function class swift struct


    【解决方案1】:

    泛型可能比依赖[AnyObject] 的协方差更适合这个问题。 countElements 的一个版本在可选数组上工作并在 nil 的情况下返回 0 可以这样:

    func countElements<T>(array: [T]?) -> Int {
        return array?.count ?? 0
    }
    

    当您使用任何类型的数组调用countElements 时,占位符T 将替换为数组中包含的元素的类型。

    注意,这个版本重载了现有的countElements,它带有一个可选的版本。如果您使用非可选或任何其他类型的集合调用它,则将调用 Swift 版本,如果您传入一个可选数组,则会调用该数组。这是一个好的做法(我认为这很好)还是坏的做法(有些人可能不赞成:),这是值得商榷的。

    适用于任何集合类型的版本是:

    func countElements<C: CollectionType>(col: C?) -> C.Index.Distance {
        return col.map { countElements($0) } ?? 0
    }
    

    【讨论】:

    • 您的泛型解决方案非常完美。但是,我属于那些会避免覆盖 Swift 标准函数的人。更具体地说,我承认我不知道 Cocoa(和其他操作系统库/框架)是否可以看到您的 countElements 版本。如果可以的话,覆盖方法可能有点不安全。
    • Cocoa 调用这个版本没有风险(即使我怀疑它不是这种可能性),因为 Swift 版本在重载解决优先级方面领先于它(即使 Swift 会隐式地将非可选参数上转换为可选参数,要求它的调用似乎在啄食顺序中较低)。我提倡以一种会导致现有调用者模棱两可的方式重载现有函数(尽管我猜你可能会在不知不觉中这样做)。
    • 好的,在您的声明中,您没有使用“public”访问控制修饰符。因此,您的 countElements 版本仅在声明它的项目中可见。那么它不应该干扰其他库。
    【解决方案2】:

    如果你使用 Any 而不是 AnyObject 你可以传递任何类型,结构体也是如此:

    class func countOfItemsInArray(array: [Any]?) -> Int
    

    这有点奇怪。

    我用过这个功能:

    func countOfItemsInArray(array: [Any]?) -> Int {
        return array != nil ? array!.count : 0
    }
    

    声明了两个 Assignment 结构并将它们放入一个数组中:

    let structOne = Assignment(name: "1", dueDate: NSDate(), subject: "1")
    let structTwo = Assignment(name: "2", dueDate: NSDate(), subject: "2")
    let myArray: [Assignment] = [structOne, structTwo]
    

    但这是有趣的部分。
    调用println(countOfItemsInArray(myArray)) 时出现错误:

    <stdin>:27:33: error: 'Assignment' is not identical to 'Any'
    println(countOfItemsInArray(myArray))
    ^
    <stdin>:17:26: note: in initialization of parameter 'array'
    func countOfItemsInArray(array: [Any]?) -> Int {
    ^
    

    所以我测试了myArray 是否属于[Any]

    println(myArray is [Any])
    

    斯威夫特说:

    <stdin>:25:17: error: 'Any' is not a subtype of 'Assignment'
    println(myArray is [Any])
    ^
    

    但是当我将 myArray 的类型注释更改为 [Any] 时,它可以工作:

    let myArray: [Any] = [structOne, structTwo]
    

    当简单地将文字传递给函数时,它也可以工作:

    countOfItemsInArray([structOne, structTwo])
    

    整个代码示例可见here

    【讨论】:

    • 我收到一个错误,“'myStructType' 与 'Any' 不同”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    相关资源
    最近更新 更多