好的,我看了this excellent answer,但我认为这不适用于我的问题(但是也许适用,我只是有点呆板)。
问题是我想基于协议(不是基类)设置调度程序对象数组,因此该数组将是协议数组,如下所示:
protocol ProtoOne { func someFunc() }
protocol ProtoTwo: ProtoOne { }
class ClassBasedOnOne: ProtoOne { func someFunc() { /* NOP */} }
class AnotherClassBasedOnOne: ProtoOne { func someFunc() { /* NOP */} }
class ClassBasedOnTwo: ProtoTwo { func someFunc() { /* NOP */} }
class AnotherClassBasedOnTwo: ProtoTwo { func someFunc() { /* NOP */} }
let arrayOfInstances: [ProtoOne] = [ClassBasedOnOne(), AnotherClassBasedOnOne(), ClassBasedOnTwo(), AnotherClassBasedOnTwo()]
很简单,是吗?
但是,我只想根据其 protocol 而不是其类对某些实例进行过滤。具有这样的功能签名:
func getInstancesOfProtoTwo(from: [Any]) -> [ProtoTwo] { return [] }
或更通用的类型,例如:
func filterForInstances<T>(of: T.Type, from: [Any]) -> [T] { return [] }
我对如何做到这一点有些困惑。甚至有可能吗?
我非常怀疑它实际上非常简单,并且我想念树木的森林。
答案 0 :(得分:1)
您只需要将compactMap
与条件强制操作as?
一起使用。
compactMap
返回一个数组,该数组包含调用给定结果的非nil结果 对该序列的每个元素进行转换。
protocol ProtoOne { func someFunc() }
protocol ProtoTwo: ProtoOne { }
class ClassBasedOnOne: ProtoOne { func someFunc() { /* NOP */} }
class AnotherClassBasedOnOne: ProtoOne { func someFunc() { /* NOP */} }
class ClassBasedOnTwo: ProtoTwo { func someFunc() { /* NOP */} }
class AnotherClassBasedOnTwo: ProtoTwo { func someFunc() { /* NOP */} }
let arrayOfInstances: [ProtoOne] = [
ClassBasedOnOne(),
AnotherClassBasedOnOne(),
ClassBasedOnTwo(),
AnotherClassBasedOnTwo()
]
let protoTwos = arrayOfInstances.compactMap { $0 as? ProtoTwo }
compactMap
非常简单,您可以看到其实现here
这是一条简单的行,老实说,我不会打扰到函数,但是如果您坚持要这么做:
func filterForInstances<T>(of: T.Type, from instances: [Any]) -> [T] {
return instances.compactMap { $0 as? T }
}
但是作为扩展,它会更好:
extension Sequence {
func keepingOnlyInstances<T>(of: T.Type) -> [T] {
return self.compactMap { $0 as? T }
}
}