Swift中如何实现双向引用的泛型类避免自引用编译错误?
解决方案:通过协议+关联类型绕开递归泛型约束
你原来的写法触发了Swift编译器对泛型约束的递归检查限制,无法直接通过编译。可以用协议定义公共能力,把类型约束的解析延迟到实例化阶段实现该需求:
第一步:定义基础协议
// 定义Parent需要满足的能力 protocol ParentProtocol: AnyObject { associatedtype ChildType: ChildProtocol var children: [ChildType] { get set } } // 定义Child需要满足的能力 protocol ChildProtocol: AnyObject { associatedtype ParentType: ParentProtocol var parent: ParentType? { get set } }
AnyObject约束保证只有类可以遵守该协议,支持使用weak修饰符避免循环引用。
第二步:实现基础泛型类
class Parent<MyChild: ChildProtocol>: ParentProtocol where MyChild.ParentType == Parent<MyChild> { var children: [MyChild] = [] } class Child<MyParent: ParentProtocol>: ChildProtocol where MyParent.ChildType == Child<MyParent> { // 注意这里加weak避免循环强引用导致内存泄漏 weak var parent: MyParent? }
where子句明确双方关联类型的对应关系,保证类型匹配。
第三步:自定义子类示例
你可以自由继承基础类扩展属性和方法,泛型会自动推导双方的具体类型,不需要额外类型转换就能访问所有自定义成员:
// 自定义Child子类 class CustomChild: Child<CustomParent> { var customChildName = "自定义子元素" func doChildThing() { print("访问父类自定义属性:\(parent?.customParentName ?? "无")") } } // 自定义Parent子类 class CustomParent: Parent<CustomChild> { var customParentName = "自定义父容器" func doParentThing() { children.forEach { child in print("访问子类自定义属性:\(child.customChildName)") child.doChildThing() } } }
测试代码
let parent = CustomParent() let child = CustomChild() child.parent = parent parent.children.append(child) // 双方方法、属性都可以正常调用 parent.doParentThing() child.doChildThing()
注意事项
- Child的parent属性必须加
weak修饰,否则两个实例会互相强引用导致内存泄漏 - 如果你需要在基础Parent/Child类里添加公共方法,因为泛型约束已经明确了对方的类型,你可以直接在基础类里访问对方遵守协议的所有成员,也可以通过类型约束访问子类扩展的成员
内容的提问来源于stack exchange,提问作者Nickkk
相关产品推荐
相关产品推荐

