Swift泛型链表中如何自动适配类型执行相等性判断?
Swift泛型链表:自动适配引用/值类型的replaceOrAppend实现
你遇到的核心问题是===仅支持引用类型(AnyObject),而==要求类型遵循Equatable,直接写死判断逻辑会导致泛型约束冲突。要实现无额外约束、自动适配的逻辑,最优雅的方式是用Swift泛型条件重载,给LinkedList分别实现针对两种类型的方法版本,让编译器自动选择对应逻辑。
具体实现
第一步:补全链表基础方法
先确保链表具备append和insertBetween的正确实现(如果还未编写):
public class LinkedListNode<T> { init(value: T) { self.value = value } public var next: LinkedListNode? public weak var previous: LinkedListNode? public var value: T } struct LinkedList<T>: Sequence { internal var head: LinkedListNode<T>? internal unowned var tail: LinkedListNode<T>? // 原有的insert方法 @discardableResult public mutating func insert(_ value: T, after: LinkedListNode<T>) -> LinkedListNode<T> { if after === tail { return append(value) } else { let node = LinkedListNode<T>(value: value) insertBetween(node, after: after, before: after.next) return node } } // 新增append方法 @discardableResult public mutating func append(_ value: T) -> LinkedListNode<T> { let newNode = LinkedListNode(value: value) if let tailNode = tail { insertBetween(newNode, after: tailNode, before: tailNode.next) } else { head = newNode } tail = newNode return newNode } // 新增insertBetween辅助方法 private mutating func insertBetween(_ node: LinkedListNode<T>, after: LinkedListNode<T>?, before: LinkedListNode<T>?) { node.previous = after node.next = before after?.next = node before?.previous = node if head == nil { head = node } } // 实现Sequence协议,支持first(where:) public func makeIterator() -> LinkedListIterator<T> { LinkedListIterator(current: head) } } // 链表迭代器实现 struct LinkedListIterator<T>: IteratorProtocol { var current: LinkedListNode<T>? mutating func next() -> LinkedListNode<T>? { let temp = current current = current?.next return temp } }
第二步:添加条件重载的replaceOrAppend方法
通过扩展给LinkedList添加两个版本的replaceOrAppend,分别对应引用类型和值类型:
extension LinkedList { // 处理类对象:用===判断引用相等 @discardableResult public mutating func replaceOrAppend(_ value: T) -> LinkedListNode<T> where T: AnyObject { if let existingNode = first(where: { $0.value === value }) { existingNode.value = value return existingNode } else { return append(value) } } // 处理值类型(Int、结构体等):用==判断内容相等 @discardableResult public mutating func replaceOrAppend(_ value: T) -> LinkedListNode<T> where T: Equatable { if let existingNode = first(where: { $0.value == value }) { existingNode.value = value return existingNode } else { return append(value) } } // 兜底处理不支持的类型 @discardableResult public mutating func replaceOrAppend(_ value: T) -> LinkedListNode<T> { fatalError("类型 \(T.self) 必须是类对象或遵循Equatable协议") } }
为什么这样可行?
- 当传入类对象时,编译器自动匹配
where T: AnyObject的方法,用===做引用判断; - 当传入Int、String或自定义结构体(只要遵循
Equatable),编译器会选择where T: Equatable的版本,用==做内容判断; - 如果传入既不是类也不遵循
Equatable的类型,会直接抛出错误,避免无意义的操作。
使用示例
// 测试值类型 var intList = LinkedList<Int>() intList.replaceOrAppend(5) intList.replaceOrAppend(5) // 替换已有节点 print(intList.map { $0.value }) // 输出 [5] // 测试引用类型 class User { var name: String init(name: String) { self.name = name } } var userList = LinkedList<User>() let user1 = User(name: "Alice") userList.replaceOrAppend(user1) let user2 = User(name: "Alice") userList.replaceOrAppend(user2) // 不同引用,追加新节点 print(userList.map { $0.value.name }) // 输出 ["Alice", "Alice"] let user3 = user1 userList.replaceOrAppend(user3) // 相同引用,替换已有节点
内容的提问来源于stack exchange,提问作者David Rector
相关产品推荐
相关产品推荐

