[英]How to make a protocol extend another protocol and provide default implementation for it in Swift?
我有一個 BinarySearchTree 協議,並希望它的所有實現都符合 Sequence 協議。 由於 traverse 方法足以進行迭代,因此我想為 Sequence 所需的 makeIterator 方法提供一個默認實現,以便 BinarySearchTree 的任何實現都可以迭代,而無需進一步執行任何操作。 但是編譯器給出了兩個錯誤:
我為 LinkedList 做了類似的事情,並且效果很好。
這里有什么問題?
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
}
}
}
}
問題來自min()
/ max()
要求:
func min() -> (Key, Value)?
func max() -> (Key, Value)?
如果您將它們注釋掉,代碼就會生成。
Sequence
還公開了這兩個函數,但是它們是僅當Element
是Comparable
時才可用的擴展的一部分,這不是您的情況,因此不確定為什么它會混淆編譯器。
另一種解決方法是讓BinarySearchTreeImp
聲明Iterator
類型別名:
typealias Iterator = AnyIterator<(Key, Value)>
,這也會使編譯器靜音,但是對於未來的一致性尚不清楚是否需要添加它來解決半模糊的編譯器錯誤消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.