如何扩展 swift 数组以访问特定类型的成员?
如果一个数组包含继承自同一个父类(super class)的多个类的实例,这就是相关的。理想情况下,它会适本地执行类型检查。
一些不太行得通的想法和事情:
使用 filter(_:)
方法工作正常,但确实强制类型安全。例如:
protocol MyProtocol { }
struct TypeA: MyProtocol { }
struct TypeB: MyProtocol { }
let myStructs:[MyProtocol] = [ TypeA(), TypeA(), TypeB() ]
let filteredArray = myStructs.filter({ $0 is TypeA })
filteredArray
包含正确的值,但类型仍然是 [MyProtocol]
而不是 [TypeA]
。我希望将最后一个替换为 let filteredArray = myStructs.filter({ $0 is TypeA }) as! [TypeA]
会解决这个问题,但项目因 EXEC_BAD_INSTRUCTION
而失败,我不明白。也许类型转换数组是不可能的?
理想情况下,此行为可以包含在数组扩展中。以下不编译:
extension Array {
func objectsOfType<T:Element>(type:T.Type) -> [T] {
return filter { $0 is T } as! [T]
}
}
这里似乎至少有两个问题:类型约束 T:Element
似乎不起作用。我不确定基于泛型类型添加约束的正确方法是什么。我在这里的意图是说 T
是 Element
的子类型。此外,第 3 行存在编译时错误,但这可能只是传播相同的错误。
最佳答案
SequenceType
有一个 flatMap()
方法作为“可选过滤器”:
extension SequenceType {
/// Return an `Array` containing the non-nil results of mapping
/// `transform` over `self`.
///
/// - Complexity: O(*M* + *N*), where *M* is the length of `self`
/// and *N* is the length of the result.
@warn_unused_result
@rethrows public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}
结合 matt 的建议使用 as?
而不是 is
你
可以用作
let myStructs:[MyProtocol] = [ TypeA(), TypeA(), TypeB() ]
let filteredArray = myStructs.flatMap { $0 as? TypeA }
现在 filteredArray
的类型被推断为 [TypeA]
。
作为一种扩展方法,它会是
extension Array {
func objectsOfType<T>(type:T.Type) -> [T] {
return flatMap { $0 as? T }
}
}
let filteredArray = myStructs.objectsOfType(TypeA.self)
注意:对于 Swift >= 4.1,将 flatMap
替换为 compactMap
。
关于arrays - 扩展 Swift 数组以按类型过滤元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33112114/