swift - 为什么我必须放弃 Swift 类的协议一致性以进行数组扩展?
问题描述
我正在实现一个树模型。每种节点类型都可以选择多种功能。我用一个 base 来实现它class Node {}
,然后是许多协议,用默认实现来描述这些功能。然后我有最终类,从 Node 派生,并符合一些协议列表,来描述我的结构。
每个协议都有以下样式的关联代码:
protocol Protocol {}
typealias ProtocolConformingNode = Node & Protocol
extension Node
{
public var isProtocolConforming: Bool {
return asProtocolConforming != nil
}
public var asProtocolConforming: ProtocolConformingNode? {
return self as? ProtocolConformingNode
}
}
我使用Node & Protocol
这样我就可以对返回的项目使用其他与协议相关的查询,例如asOtherProtocolConforming
.
这一切都很好,直到我处理ProtocolConformingNode
. 最初我遇到了过滤节点+协议数组的问题,我想在过滤后保持一致性:
extension Array where Element: Node
{
var someFilter: [Element] {
return self
}
}
let array = [ProtocolConformingNode]()
let filteredArray = array.someFilter
这给出了以下错误:
[ProtocolConformingNode]' (aka 'Array<Node & Protocol>') requires that 'ProtocolConformingNode' conform to 'AnyObject'
这感觉有点奇怪,但我认为它属于之前在 SO 上讨论过的一个问题:协议不符合自身?
我决定对于我使用它的极少数情况来说,类型擦除我的所有协议会太多,所以我会满足于在过滤后转换我的节点。请注意,我没有Element
在以下代码中使用,而是明确使用Node
, 和Element == Node
:
extension Array where Element == Node
{
var someFilter: [Node] {
return self
}
}
let array = [ProtocolConformingNode]()
let filteredArray = array.someFilter as! [ProtocolConformingNode]
这现在给出了错误:
'[ProtocolConformingNode]' (aka 'Array<Node & Protocol>') is not convertible to 'Array<Node>'
这让我感觉很奇怪。我可以让它像这样工作:
let filteredArray = (array as [Node]).someFilter as! [ProtocolConformingNode]
但是我为什么要在这里投呢?下面是如何工作的?
var nodes = [Node]()
var protocolConformingNodes = [ProtocolConformingNode]()
nodes.append(contentsOf: protocolConformingNodes)
什么时候:
mutating func append<S>(contentsOf newElements: S) where Element == S.Element, S : Sequence
解决方案
这与您链接的 SO 帖子相同。特别是,您应该阅读 Hamish 的回答。IMO,这是语言的一个缺点,只有在具有静态或初始化程序要求时才会成为问题Protocol
,在这种情况下,它没有。
快速而肮脏的解决方法是使用@objc
. 完整的代码看起来像
class Node {}
@objc protocol Protocol {}
typealias ProtocolConformingNode = Node & Protocol
extension Array where Element: Node
{
var someFilter: [Element] {
return self
}
}
let array = [ProtocolConformingNode]()
let filteredArray = array.someFilter // Yay! No error this time.
推荐阅读
- python - How to get value of if I know only the value of corresponding ?
- firebase - 如何以只读模式查询firebase
- python - 如何检测这些基于矩形的对象的碰撞?
- python - 如何导入 fernet?
- sql - Postgre 等效于 MSSQL 外部应用
- javascript - 如何从“ajax 成功”返回承诺?
- regex - 正则表达式,如何忽略数字的句点?
- python-3.x - 为什么从 mpi4py 导入 MPI 会中断对 mpiexec 的子进程调用?
- python - 通过将某些列转换为行来重塑 pandas 数据框
- javascript - 在nodejs中保存从url保存的图像时出现问题