Can someone explain why this code throws error?
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
And next question: Is the only way to add subclass elements is by adding them one by one in for loop?
If you check the headers:
public mutating func append(newElement: Element)
public mutating func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C)
Note the difference in type specifiers. While append
enables you to add anything that is an Element
, that is, including sublasses, appendContentsOf
forces you to use an array with exactly the same element type (subclasses not allowed).
It would work with:
let subclassItems = [Base](count: 3, repeatedValue: SubclassOfBase())
I would consider this to be a bug because this could be easily fixed by improving the function header (well, this also needs an extension to where
clauses because detecting generic subtypes is impossible right now).
Some possible workarounds:
Append directly for every item
subclassItems.forEach {items.append($0)}
Declare a helper method for Arrays (will work for Array
, not for generic CollectionType
)
extension Array {
public mutating func appendContentsOf(newElements: [Element]) {
newElements.forEach {
self.append($0)
}
}
}
Direct cast
items.appendContentsOf(subclassItems as [Base])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With