如何使用不同类的数组创建新数组

时间:2016-09-30 04:34:11

标签: swift

我有两个类,都是SuperClass的子类:

class A: SuperClass {
    ...
    static let arrayA: [A] = [a, b, c]
}

class B: SuperClass {
    ...
    static let arrayB: [B] = [1, 2, 3]
}

然后我想创建一个类型为SuperClass的新数组:

let newArray: [SuperClass] = A.arrayA + B.arrayB
  

这里我遇到了一个错误:表达式的类型不明确而没有更多的上下文

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您必须将每个数组从[A][B]类型转换为[SuperClass]类型。最好使用map完成此操作。然后你可以把它们组合起来。

class SuperClass : CustomStringConvertible {
  var description: String { return "super" }
}
class A: SuperClass {
  let value: String
  init(_ value: String) { self.value = value }
  static let arrayA: [A] = [A("a"), A("b"), A("c")]
  override var description: String { return "\(value)" }
}

class B: SuperClass {
  let value: Int
  init(_ value: Int) { self.value = value }
  static let arrayB: [B] = [B(1), B(2), B(3)]
  override var description: String { return "\(value)" }
}

// convert each array to [SuperClass] and combine them
let newArray: [SuperClass] = A.arrayA.map { $0 as SuperClass } + B.arrayB.map { $0 as SuperClass }

print(newArray) // -> "[a, b, c, 1, 2, 3]\n"

答案 1 :(得分:1)

值得注意的是,因为泛型在Swift中是不变的,没有任何编译器魔法,所以甚至不会编译:

let newArray : [SuperClass] = A.arrayA

当您尝试将Array<A>转换为Array<SuperClass>时,它们是完全不相关的类型(请参阅this Q&A)。

虽然,对于Swift中的一些本机集合类型(Array是其中之一),编译器做了一些魔术,它允许集合之间的隐式转换与子类类型的元素对于具有超类类型元素的那些(以及抽象它们所遵循的类型的具体类型)。

然而,当谈到这一行时:

let newArray : [SuperClass] = A.arrayA + B.arrayB

对于编译器而言,解析起来太多了,因为它必须为上下文找到正确的+重载,这可能是以下任何一种:

public func +<C : RangeReplaceableCollection, S : Sequence where S.Iterator.Element == C.Iterator.Element>(lhs: C, rhs: S) -> C
public func +<C : RangeReplaceableCollection, S : Sequence where S.Iterator.Element == C.Iterator.Element>(lhs: S, rhs: C) -> C
public func +<RRC1 : RangeReplaceableCollection, RRC2 : RangeReplaceableCollection where RRC1.Iterator.Element == RRC2.Iterator.Element>(lhs: RRC1, rhs: RRC2) -> RRC1

并且必须推断您希望将A.arrayAB.arrayB的元素类型转换为SuperClass

为了提供帮助,你可以简单地将双方都投向[SuperClass]

let newArray = A.arrayA as [SuperClass] + B.arrayB as [SuperClass]

或做:

let newArray : [SuperClass] = A.arrayA as [SuperClass] + B.arrayB

或(最有趣的解决方案),您可以为+定义一个特殊于两个Array<T>操作数的重载:

func +<T>(lhs: [T], rhs: [T]) -> [T] {
    var lhs = lhs
    lhs.reserveCapacity(lhs.count + rhs.count)
    lhs.append(contentsOf: rhs)
    return lhs
}

(这与现有的standard library overloads)具有类似的实现

现在可行:

let newArray : [SuperClass] = A.arrayA + B.arrayB

据我所知,当操作数相等的元素类型的泛型约束是次要的(即where子句)时,编译器只会遇到问题。然而,这种重载将其作为主要约束条件。

答案 2 :(得分:0)

只是在我的桌面上发布我试过的东西:

class User:NSObject{
    var name: String
    var age: Int

    init(n:String, a:Int) {
        self.name = n
        self.age = a
    }
}

class Section: User {
    static let arrayA: [Section] = [Section(n: "John", a: 20), Section(n: "Mariah", a: 18)]
}

class Library: User {
    static let arrayB: [Library] = [Library(n: "Martin", a: 20), Library(n: "Mariah", a: 18)]
}

最后:

let newArray:[User] = Section.arrayA.map { $0 as User } + Library.arrayB.map { $0 as User }
print(newArray)

输出:

(lldb) po newArray
▿ 4 elements
  - [0] : <TestSwift2.Section: 0x7fdb4b43d460>
  - [1] : <TestSwift2.Section: 0x7fdb4b43d4e0>
  - [2] : <TestSwift2.Library: 0x7fdb4b43e4b0>
  - [3] : <TestSwift2.Library: 0x7fdb4b43e4e0>

(lldb) po newArray[0].age
20

(lldb) po newArray[0].name
"John"