排序一组协议,寻找父协议

时间:2019-04-22 15:02:47

标签: swift protocols

好的,我看了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 [] }

我对如何做到这一点有些困惑。甚至有可能吗?

我非常怀疑它实际上非常简单,并且我想念树木的森林。

1 个答案:

答案 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 }
    }
}