简体   繁体   English

如何让一个协议扩展另一个协议并在Swift中为其提供默认实现?

[英]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:但是编译器给出了两个错误:

  • Type 'BinarySearchTreeImp' does not conform to protocol 'BinarySearchTree'类型“BinarySearchTreeImp”不符合协议“BinarySearchTree”
  • Type 'BinarySearchTreeImp' does not conform to protocol 'Sequence'类型“BinarySearchTreeImp”不符合协议“序列”

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还公开了这两个函数,但是它们是仅当ElementComparable时才可用的扩展的一部分,这不是您的情况,因此不确定为什么它会混淆编译器。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM