gpt4 book ai didi

swift - 为什么我必须放弃 Swift 类的协议(protocol)一致性以进行数组扩展?

转载 作者:行者123 更新时间:2023-11-30 10:46:57 24 4
gpt4 key购买 nike

我正在实现一个树模型。每种节点类型都可以有多种功能可供选择。我使用基 class Node {} 来实现此功能,然后使用许多带有默认实现的协议(protocol)来描述功能。然后我有最终的类,从 Node 派生,并符合一些协议(protocol)列表,来描述我的结构。

每个协议(protocol)都有以下样式的关联代码:

protocol Protocol {}

typealias ProtocolConformingNode = Node & Protocol

extension Node
{
public var isProtocolConforming: Bool {
return asProtocolConforming != nil
}

public var asProtocolConforming: ProtocolConformingNode? {
return self as? ProtocolConformingNode
}
}

我使用节点和协议(protocol),以便我可以对返回的项目使用其他协议(protocol)相关的查询,例如asOtherProtocolConforming

这一切都工作正常,直到我处理 ProtocolConformingNode 数组。最初,我在过滤节点数组+协议(protocol)时遇到了问题,我想在过滤后保持一致性:

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'

这感觉有点奇怪,但我认为它属于之前讨论过的问题:Protocol doesn't conform to itself?

我认为对于我使用它的极少数情况来说,类型删除我的所有协议(protocol)太过分了,所以我会满足于在过滤后转换我的节点。请注意,我在以下代码中没有使用 Element,而是显式使用 NodeElement == 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 帖子是同一个问题。特别是,你应该阅读哈米什的回答。 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.

关于swift - 为什么我必须放弃 Swift 类的协议(protocol)一致性以进行数组扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55569877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com