【问题标题】:Swift array of type [SuperClass] with elements of type [Subclass][SuperClass] 类型的 Swift 数组,元素类型为 [Subclass]
【发布时间】:2015-10-21 09:49:59
【问题描述】:

有人可以解释为什么这段代码会抛出错误吗?

class Base {}
class SubclassOfBase: Base {}

let baseItems = [Base](count: 1, repeatedValue: Base())
let subclassItems = [SubclassOfBase](count: 3, repeatedValue: SubclassOfBase())

var items = [Base]()
items.append(SubclassOfBase()) //OK
items.appendContentsOf(baseItems) //OK
items.appendContentsOf(subclassItems) //cannot invoke with argument of type [SubclassOfBase]
items.append(subclassItems.first!) //OK

下一个问题:添加子类元素的唯一方法是在 for 循环中逐个添加吗?

【问题讨论】:

  • 可能的解决方法:items.appendContentsOf(subclassItems as [Base]).

标签: arrays swift


【解决方案1】:

如果您检查标题:

public mutating func append(newElement: Element)

public mutating func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C)

注意类型说明符的区别。虽然append 允许您添加任何属于Element 的内容,即包括子类,但appendContentsOf 强制您使用具有完全相同元素类型的数组(不允许子类)。

它适用于:

let subclassItems = [Base](count: 3, repeatedValue: SubclassOfBase())

我认为这是一个错误,因为可以通过改进函数头来轻松解决这个问题(嗯,这也需要扩展 where 子句,因为目前无法检测泛型子类型)。

一些可能的解决方法:

  1. 为每个项目直接附加

    subclassItems.forEach {items.append($0)}
  2. 为数组声明一个辅助方法(适用于Array,不适用于通用CollectionType

    extension Array {
        public mutating func appendContentsOf(newElements: [Element]) {
            newElements.forEach {
                self.append($0)
            }
        }
    }
  3. 直接投射

    items.appendContentsOf(subclassItems as [Base])

【讨论】:

  • 您能否详细说明您将如何修复函数头?
  • @CouchDeveloper 好吧,我们无法修复它,但 Apple 可以。将其报告为错误。
  • 类型约束中的where 子句要么要求类型相等,要么符合某个协议。在给定的问题中,我们需要一些新的谓词,例如 is_a 类型,例如:&lt;C : CollectionType where C.Generator.Element &lt;= Element&gt;.
  • @CouchDeveloper 是的,这就是问题所在。 where 子句目前有点限于处理子类型。
  • 或`extension CollectionType where Generator.Element: Base {``
猜你喜欢
  • 1970-01-01
  • 2016-06-21
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-29
相关资源
最近更新 更多