簡體   English   中英

如何讓一個協議擴展另一個協議並在Swift中為其提供默認實現?

[英]How to make a protocol extend another protocol and provide default implementation for it in Swift?

我有一個 BinarySearchTree 協議,並希望它的所有實現都符合 Sequence 協議。 由於 traverse 方法足以進行迭代,因此我想為 Sequence 所需的 makeIterator 方法提供一個默認實現,以便 BinarySearchTree 的任何實現都可以迭代,而無需進一步執行任何操作。 但是編譯器給出了兩個錯誤:

  • 類型“BinarySearchTreeImp”不符合協議“BinarySearchTree”
  • 類型“BinarySearchTreeImp”不符合協議“序列”

我為 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還公開了這兩個函數,但是它們是僅當ElementComparable時才可用的擴展的一部分,這不是您的情況,因此不確定為什么它會混淆編譯器。

另一種解決方法是讓BinarySearchTreeImp聲明Iterator類型別名:

typealias Iterator = AnyIterator<(Key, Value)>

,這也會使編譯器靜音,但是對於未來的一致性尚不清楚是否需要添加它來解決半模糊的編譯器錯誤消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM