6

I'm trying to find the best way to merge Swift arrays, that are not of same type, but they have same superclass. I've already read all the tutorials so I know I can use:

var array = ["Some", "Array", "of", "Strings"]
array += ["Another string", "and one more"]
array.append(["Or", "This"])

In this case array variable infers the type [String]. The problem I have relates to the next hypothetical situation with classes (properties do not matter in this case, just there to make a difference between classes):

class A {
    var property1 : String?
}

class B : A {
    var property2: String?
}

class C : A {
    var property3: String?
}

So I create an array of class A and B objects:

var array = [ A(), B(), A(), B() ]

This array should now be of type [A], since this is the inferred type by both A and B classes.

Now I want to append objects to this array, that are of type C.

var anotherArray = [ C(), C(), C() ]

Since anotherArray is now of type [C], we should still be able to append it, since all C instances respond to A methods. So we try:

array += anotherArray

This fails due to:

Binary operator '+=' cannot be applied to operands of type '[A]' and '[C]'.

Similar story with using append method. While this does make sense, I cannot understand why this couldn't work.

Can someone explain why this is not working? What is the best solution to this problem?

The only sensible solution I found is to define the type of anotherArray to be [A], but are there any better ones or this is correct?

var anotherArray : [A] = [ C(), C(), C() ]

Thanks!

3 Answers 3

10

If C inherits from A then you can "upcast" an array of type [C] to an array of type [A]

array += anotherArray as [A]

Alternatively, use (tested with Swift 4)

array.append(contentsOf: anotherArray)
Sign up to request clarification or add additional context in comments.

Comments

2

In addition to Martin's answer, you could create a protocol that all of the classes conform to and then when creating your array, make it's type that protocol.

Then you can add any of the classes to it without casting.

2 Comments

Or var anotherArray: [A] = [ C(), C(), C() ] so it knows which type to use in the array.
If array has type [P] and anotherArray type [B] where B confoms to the protocol P, then you have to upcast as well. array += anotherArray does not compile.
0

you can merge almost everything. the only requirement is that all elements of resulting array must conform to the same protocol.

let arr1 = [1,2,3]          // [Int]
let arr2 = [4.0,5.0,6.0]    // [Double]
let arr3 = ["a","b"]        // [String]

import Foundation // NSDate
let arr4 = [NSDate()]       // [NSDate]

// the only common protocol in this case is Any
var arr:[Any] = []

arr1.forEach { arr.append($0) }
arr2.forEach { arr.append($0) }
arr3.forEach { arr.append($0) }
arr4.forEach { arr.append($0) }

print(arr) // [1, 2, 3, 4.0, 5.0, 6.0, "a", "b", 2016-02-15 08:25:03 +0000]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.