尝试创建一个用于在树中创建不同节点的协议(protocol)。简化版本是:
protocol NodeElement {
var children: [NodeElement] { get }
}
此协议(protocol)可用于创建可用于在树中创建节点的结构。
struct TextNode: NodeElement {
var text: String
var children: [NodeElement]
}
struct NumberNode: NodeElement {
var number: Int
var children: [NodeElement]
}
使用这些结构,可以创建包含不同类型的树。
let root = TextNode(text: "Hello", Children: [NumberNode(...), ...])
我希望 NodeElement 符合序列协议(protocol),以允许在 for...in
循环内进行前序树遍历。
这可以通过
来完成protocol NodeElement: Sequence { ... }
extension NodeElement {
func makeIterator() -> AnyIterator<NodeElement> {
var stack: [NodeElement] = [self]
return AnyIterator {
if let next = stack.first {
stack.remove(at: 0)
stack.insert(contentsOf: next.content, at: 0)
return next
}
return nil
}
}
}
如果这样做,则会出现以下错误:
error: protocol 'NodeElement' can only be used as a generic constraint
because it has Self or associated type requirements
var content: [NodeElement] { get }
^
即使我相信我完全遵守序列协议(protocol),也会发生这种情况。
如果不将 NodeElement 创建为 struct 并让所有节点都继承它,有什么方法可以实现此功能吗?
最佳答案
NodeElement 有对其自身的引用,因此不能用于定义具体类型。因此,您将无法将其设为序列。
但是,您可以通过简单地将计算变量添加到协议(protocol)而不是使其本身成为序列来实现类似的效果。
例如:
extension NodeElement
{
var treeNodes : AnyIterator<NodeElement>
{
var stack: [NodeElement] = [self]
return AnyIterator {
if let next = stack.first {
stack.remove(at: 0)
stack.insert(contentsOf: next.children, at: 0)
return next
}
return nil
}
}
}
然后,您将能够使用该变量在 for ... in 循环中使用您的协议(protocol):
for node in root.treeNodes
{
...
}
关于swift - 协议(protocol)符合Sequence协议(protocol),同时消除通用约束问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43144738/