Swift 通过协议数组进行排序,查找父协议

Swift 通过协议数组进行排序,查找父协议,swift,protocols,Swift,Protocols,好吧,我看了,但我不认为这适用于我的问题(但可能是这样,我只是迟钝) 问题是,我想基于协议(而不是基类)设置一个dispatcher对象数组,因此该数组将是一个协议数组,如下所示: protocol ProtoOne { func someFunc() } protocol ProtoTwo: ProtoOne { } class ClassBasedOnOne: ProtoOne { func someFunc() { /* NOP */} } class AnotherClassBased

好吧,我看了,但我不认为这适用于我的问题(但可能是这样,我只是迟钝)

问题是,我想基于协议(而不是基类)设置一个dispatcher对象数组,因此该数组将是一个协议数组,如下所示:

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()]
func filterForInstances<T>(of: T.Type, from: [Any]) -> [T] { return [] }
够简单了吧

但是,我只想根据它们的协议而不是它们的类筛选某些实例。具有如下函数签名:

func getInstancesOfProtoTwo(from: [Any]) -> [ProtoTwo] { return [] }
或者更一般的类型,如:

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()]
func filterForInstances<T>(of: T.Type, from: [Any]) -> [T] { return [] }
func filterForInstances(属于:T.Type,from:[Any])->[T]{return[]}
我不知道该怎么做。有可能吗

我有一种恶毒的怀疑,那就是它实际上非常简单,我正在为树木而错过森林。

您只需要将条件强制操作与
一起使用,如?

压缩图 返回一个数组,该数组包含调用给定 与此序列的每个元素的转换

compactMap
非常简单,您可以看到它的实现

这是一条简单的线,老实说,我不会费心提取到函数,但如果您坚持:

func filterForInstances<T>(of: T.Type, from instances: [Any]) -> [T] {
    return instances.compactMap { $0 as? T }
}
func filterForInstances(属于:T.类型,来自实例:[Any])->[T]{
return instances.compactMap{$0 as?T}
}
但作为一种延伸,它会更好:

extension Sequence {
    func keepingOnlyInstances<T>(of: T.Type) -> [T] {
        return self.compactMap { $0 as? T }
    }
}
扩展序列{
函数仅保留状态(属于:T.Type)->[T]{
返回self.compactMap{$0作为?T}
}
}

该死,太快了。酷。是的,我可能会用这张地图。谢谢此外,您还应该了解它是如何制作的:
compactMap
非常简单,您可以看到它的实现,我非常感谢您的回答。我可能仍然需要对协议进行排序,因为我正在使用一组“同级”协议来创建专门的处理程序(我搜索实现一个协议的类的实例,然后将它们转换到我定义的另一个协议。这很烦人,但我正在编写一个API测试工具,无法控制API协议)。在不了解太多细节的情况下,我看到了三种方法:1)使您的协议扩展API协议,并添加您需要的内容;2)直接对API协议进行扩展;或3)作为最后手段,使用类似“asMyProtocol”(idk是更好的名称)的函数扩展每个API协议这要求一致性对象按照他们所看到的方式进行转换。这是一种常见的模式:切换情况(或其他分支语句)通常可以更好地表示为方法调用,其中几个可能的对象中的一个以适合上下文的方式响应(这就是OO的家伙们总是垂涎三尺的多态性:p)然而,我会改变这种模式。检查特定类型的一致性是设计不佳的一个指标。通常最好只要求符合协议的实例做一些事情(通过调用函数),并让实例自行决定是否应执行或忽略调用。的可能重复项(请注意,在当前Swift中,
flatMap
必须替换为
compactMap
)。关于类型筛选的要点很好。谢谢!