[英]How to make a protocol extend another protocol and provide default implementation for it in Swift?
I have a BinarySearchTree protocol and want to make all implementations of it to conform to Sequence protocol.我有一个 BinarySearchTree 协议,并希望它的所有实现都符合 Sequence 协议。 Since the traverse method is enough for iteration, I wanted to provide a default implementation for makeIterator method which is required by Sequence so that any implementation of BinarySearchTree becomes iterable without doing anything further.由于 traverse 方法足以进行迭代,因此我想为 Sequence 所需的 makeIterator 方法提供一个默认实现,以便 BinarySearchTree 的任何实现都可以迭代,而无需进一步执行任何操作。 But compiler gives two errors:但是编译器给出了两个错误:
I have done a similar thing for LinkedList and it worked fine.我为 LinkedList 做了类似的事情,并且效果很好。
What is wrong here?这里有什么问题?
protocol BinarySearchTree: Sequence where Element == (Key, Value) {
associatedtype Key: Comparable
associatedtype Value
func insert(key: Key, value: Value)
func remove(key: Key) -> Value?
func find(key: Key) -> Value?
func findPredecessor(key: Key) -> (Key, Value)?
func findSuccessor(key: Key) -> (Key, Value)?
func min() -> (Key, Value)?
func max() -> (Key, Value)?
func removeMin() -> (Key, Value)?
func removeMax() -> (Key, Value)?
func traverse() -> AnySequence<(Key, Value)>
}
extension BinarySearchTree {
func makeIterator() -> AnyIterator<(Self.Key, Self.Value)> {
return traverse().makeIterator()
}
}
fileprivate class BSTNode<Key:Comparable, Value> {
let key: Key
let value: Value
var left: BSTNode<Key, Value>?
var right: BSTNode<Key, Value>?
unowned var parent: BSTNode<Key, Value>?
var isLeaf: Bool {
left == nil && right == nil
}
init(key: Key, value: Value){
self.key = key
self.value = value
}
func toTuple() -> (Key, Value) {
return (self.key, self.value)
}
func min() -> BSTNode {
guard let left = left else { return self }
return left.min()
}
func max() -> BSTNode {
guard let right = right else { return self }
return right.max()
}
func find(key: Key) -> BSTNode? {
if key == self.key {
return self
}
if key < self.key {
guard let left = left else { return nil }
return left.find(key: key)
}
guard let right = right else { return nil }
return right.find(key: key)
}
func findPredecessor() -> BSTNode? {
if let left = left { return left.max() }
var current = self
while let parent = current.parent {
if current === parent.right {
return parent
}
current = parent
}
return nil
}
func findSuccessor() -> BSTNode? {
if let right = right { return right.min() }
var current = self
while let parent = current.parent {
if current === parent.left {
return parent
}
current = parent
}
return nil
}
func insert(key: Key, value: Value) -> BSTNode {
if key <= self.key {
if let left = left {
return left.insert(key: key, value: value)
} else {
left = BSTNode(key: key, value: value)
left!.parent = self
return left!
}
} else {
if let right = right {
return right.insert(key: key, value: value)
} else {
right = BSTNode(key: key, value: value)
right!.parent = self
return right!
}
}
}
func delete() {
if isLeaf {
promoteChild(nil)
return
}
if left == nil {
promoteChild(right)
right = nil
return
}
if right == nil {
promoteChild(left)
left = nil
return
}
let successor = right!.min()
assert(successor.parent != nil)
successor.left = left
if successor.parent === self {
promoteChild(successor)
} else {
let successorsParent = successor.parent!
promoteChild(successor)
// successor must be left child unless it is right child of self
successorsParent.left = nil
successor.max().right = self.right
}
left = nil
right = nil
}
private func promoteChild(_ child: BSTNode?) {
guard let parent = parent else { return }
child?.parent = parent
if parent.left === self {
parent.left = child
} else {
parent.right = child
}
self.parent = nil
}
}
class BinarySearchTreeImp<Key: Comparable, Value> : BinarySearchTree {
private var root: BSTNode<Key, Value>?
init(){}
func min() -> (Key, Value)? {
return root?.min().toTuple()
}
func max() -> (Key, Value)? {
return root?.max().toTuple()
}
func find(key: Key) -> Value? {
return root?.find(key: key)?.value
}
func findPredecessor(key: Key) -> (Key, Value)? {
return root?.find(key: key)?.findPredecessor()?.toTuple()
}
func findSuccessor(key: Key) -> (Key, Value)? {
return root?.find(key: key)?.findSuccessor()?.toTuple()
}
func insert(key: Key, value: Value) {
if let root = root {
root.insert(key: key, value: value)
} else {
root = BSTNode(key: key, value: value)
}
}
func remove(key: Key) -> Value? {
guard let node = root?.find(key: key) else { return nil }
let result = node.value
node.delete()
return result
}
func removeMin() -> (Key, Value)? {
guard let node = root?.min() else {
return nil
}
node.delete()
return node.toTuple()
}
func removeMax() -> (Key, Value)? {
guard let node = root?.max() else {
return nil
}
node.delete()
return node.toTuple()
}
func traverse() -> AnySequence<(Key, Value)> {
return AnySequence { () -> AnyIterator<(Key, Value)> in
var currentNode: BSTNode<Key, Value>? = self.root?.min()
return AnyIterator {
let result = currentNode?.toTuple()
currentNode = currentNode?.findSuccessor()
return result
}
}
}
}
The problem comes from the min()
/ max()
requirements:问题来自min()
/ max()
要求:
func min() -> (Key, Value)?
func max() -> (Key, Value)?
If you comment them out, the code builds.如果您将它们注释掉,代码就会生成。
Sequence
also exposes these two functions, however they are part of an extension available only if Element
is Comparable
, which is not your case, so not sure why it confuses the compiler. Sequence
还公开了这两个函数,但是它们是仅当Element
是Comparable
时才可用的扩展的一部分,这不是您的情况,因此不确定为什么它会混淆编译器。
Another workaround is to have BinarySearchTreeImp
declare the Iterator
typealias:另一种解决方法是让BinarySearchTreeImp
声明Iterator
类型别名:
typealias Iterator = AnyIterator<(Key, Value)>
, this will also silence the compiler, however it's not clear for future conformances that this will need to be added to solve a semi-obscure compiler error message. ,这也会使编译器静音,但是对于未来的一致性尚不清楚是否需要添加它来解决半模糊的编译器错误消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.