繁体   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