对一系列协议进行排序,寻找父协议
Sorting Through An Array Of Protocols, Looking for Parent Protocols
好的,我查看了 this excellent answer,但我认为它不适用于我的问题(但也许适用,我只是太迟钝了)。
问题是我想基于一个协议(而不是一个基础 class)设置一个调度程序对象数组,所以这个数组将是一个协议数组,如下所示:
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()]
够简单吧?
但是,我只想根据它们的 协议 而不是它们的 class 来过滤某些实例。使用这样的函数签名:
func getInstancesOfProtoTwo(from: [Any]) -> [ProtoTwo] { return [] }
或者更通用的类型,例如:
func filterForInstances<T>(of: T.Type, from: [Any]) -> [T] { return [] }
我有点不知道该怎么做。有可能吗?
我有一个严重的怀疑,它实际上非常简单,我只见树木不见森林。
你只需要使用 compactMap
和条件强制操作,as?
。
compactMap
Returns an array containing the non-nil results of calling the given
transformation with each element of this sequence.
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 { [=10=] as? ProtoTwo }
compactMap
其实很简单,大家可以看看它的实现here
这是一个简单的行,老实说我不会费心将其提取到函数中,但如果您坚持:
func filterForInstances<T>(of: T.Type, from instances: [Any]) -> [T] {
return instances.compactMap { [=11=] as? T }
}
但作为扩展会更好:
extension Sequence {
func keepingOnlyInstances<T>(of: T.Type) -> [T] {
return self.compactMap { [=12=] as? T }
}
}
好的,我查看了 this excellent answer,但我认为它不适用于我的问题(但也许适用,我只是太迟钝了)。
问题是我想基于一个协议(而不是一个基础 class)设置一个调度程序对象数组,所以这个数组将是一个协议数组,如下所示:
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()]
够简单吧?
但是,我只想根据它们的 协议 而不是它们的 class 来过滤某些实例。使用这样的函数签名:
func getInstancesOfProtoTwo(from: [Any]) -> [ProtoTwo] { return [] }
或者更通用的类型,例如:
func filterForInstances<T>(of: T.Type, from: [Any]) -> [T] { return [] }
我有点不知道该怎么做。有可能吗?
我有一个严重的怀疑,它实际上非常简单,我只见树木不见森林。
你只需要使用 compactMap
和条件强制操作,as?
。
compactMap
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
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 { [=10=] as? ProtoTwo }
compactMap
其实很简单,大家可以看看它的实现here
这是一个简单的行,老实说我不会费心将其提取到函数中,但如果您坚持:
func filterForInstances<T>(of: T.Type, from instances: [Any]) -> [T] {
return instances.compactMap { [=11=] as? T }
}
但作为扩展会更好:
extension Sequence {
func keepingOnlyInstances<T>(of: T.Type) -> [T] {
return self.compactMap { [=12=] as? T }
}
}