[SuperClass]类型的Swift数组,其元素类型为[Subclass]

Kub*_*bba 4 arrays swift

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

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
Run Code Online (Sandbox Code Playgroud)

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

Sul*_*han 11

如果您检查标题:

public mutating func append(newElement: Element)

public mutating func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C)
Run Code Online (Sandbox Code Playgroud)

请注意类型说明符的不同之处.虽然append允许您添加任何Element包含子类的内容,但appendContentsOf强制您使用具有完全相同元素类型的数组(不允许使用子类).

它适用于:

let subclassItems = [Base](count: 3, repeatedValue: SubclassOfBase())
Run Code Online (Sandbox Code Playgroud)

我认为这是一个bug,因为这可以通过改进函数头来轻松修复(好吧,这也需要对where子句进行扩展,因为现在检测通用子类型是不可能的).

一些可能的解决方法:

  1. 直接附加每个项目

    subclassItems.forEach {items.append($0)}
    Run Code Online (Sandbox Code Playgroud)
  2. 为数组声明一个辅助方法(适用于Array,而不是泛型CollectionType)

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

    items.appendContentsOf(subclassItems as [Base])
    Run Code Online (Sandbox Code Playgroud)