swift - 数组中的协议和关联类型
问题描述
我有一个协议Node
:
protocol Node {
var parent: Node?
var children: [Node]
}
这是由类实现的:
class TreeNode: Node {
var parent: Node?
var children: [Node]
}
但这带来了一个问题,因为TreeNode
现在访问父级给了我一个Node
,我想TreeNode
对它们进行特定的操作。所以我想将协议更改为:
protocol Node {
associatedtype T: Node
var parent: T?
var children: [T]
}
让我将类定义为:
class TreeNode: Node {
var parent: TreeNode?
var children: [TreeNode]
}
伟大的!但有一个问题。如果我想为Node
处理数组编写一个辅助方法:
func getReversedChildren<T: Node>(node: T) -> [T] {
return node.children.reversed()
}
编译器失败并出现以下错误:
Cannot convert return expression of type 'ReversedCollection<[T.T]>' to return type '[T]'
从我能收集到的关于这个问题的信息来看,我需要实现一种类型擦除机制来支持这种架构。但是如何在我的例子中做到这一点?
解决方案
您可能希望节点的父节点和子节点与节点本身的类型相同,而不仅仅是符合. 那将在协议定义中:Node
Self
protocol Node {
var parent: Self? { get set }
var children: [Self] { get set }
}
现在您可以定义具体的类(请参阅A Swift 协议要求,该要求只能通过使用最终类来满足,以了解为什么需要该类final
):
final class TreeNode: Node {
var parent: TreeNode? = nil
var children: [TreeNode] = []
}
和
func getReversedChildren<T: Node>(node: T) -> [T] {
return node.children.reversed()
}
编译没有问题。
推荐阅读
- c# - 如何在EF Core中按具有不同实体名称的多个列进行分组 - C#
- python - 如何在任务栏中不显示程序的情况下运行 python 代码
- android - RecyclerView OnClick 侦听器返回错误
- python - 在单行中打印列表元素但不使用循环
- python - grep 父 pom 版本并替换为新值
- android - 仅安装了设备凭据的 Androidx.biometric 不会在具有 Android 9 及以下版本的设备上调用回调
- cognos - 如何使用 TM1py 在 Python 和 IBM TM1 OLAP 工具之间建立连接
- javascript - 修复函数中的 no-param-reassign Eslint 问题
- node.js - 机器学习过程的 Sagemaker 用户密钥和秘密
- python - 如何按 2 列分组并在熊猫中执行计数