【问题标题】:Swift Equatable Generic type comparison inside generic function泛型函数内的 Swift Equatable 泛型类型比较
【发布时间】:2017-09-04 22:31:33
【问题描述】:

我有一个像这样的二叉树的Node 类:

class Node<T: Equatable> {
    let value: T
    let left: Node<T>?
    let right: Node<T>?

    init(value: T, left: Node<T>? = nil, right: Node<T>? = nil) {
        self.value = value
        self.left = left
        self.right = right
    }
}

这些值需要是相等的。

我可以这样测试公平性:

let a = Node(value: 8)
let b = Node(value: 7)

let c = a.value > b.value

效果很好,c: true

但是当我编写一个使用节点公平性的通用函数时,我得到了错误:

func isBinaryTree<T>(node: Node<T>) -> Bool {
    if let leftNode = node.left {
        guard leftNode.value < node.value else {
            return false
        }
        guard isBinaryTree(node: leftNode) else {
            return false
        }
    }
    if let rightNode = node.right {
        guard rightNode.value >= node.value else {
            return false
        }
        guard isBinaryTree(node: rightNode) else {
            return false
        }
    }

    return true
}

let result = isBinaryTree(node: root)

错误:

error: binary operator '<' cannot be applied to two 'T' operands guard leftNode.value < node.value ||`

我不确定为什么编译器似乎不知道为什么 T 值是 Equatable 或者为什么它不认为 leftNode 上的 TTnode

代码:

let d = Node(value: Float(3), left: Node(value: Int(8)) , right: nil)

按预期给出错误。

进一步研究,它与函数无关,因为当我尝试代码时:

let x = Node(value: 3, left: Node(value: 8) , right: nil)
let y = x.value < x.left!.value

我遇到同样的错误

【问题讨论】:

  • 你的例子c不可能,因为你的Node不是Comparable
  • 我觉得把EquatableComparable 混在一起真的很傻。谢谢!
  • 您真正需要的是Comparable 协议。 Equatable 协议只需要实现相等 (==) 函数即可实现一致性。比较函数(如&lt;)只保证由Comparable协议实现。
  • @richy 在像这样的任意树中,它的可比性没有任何意义。您应该只访问value 并比较它们

标签: swift generics equatable


【解决方案1】:

在一般情况下,两个 Node 对象是不可比较的。这取决于它们所在的树的类型。例如,如果节点仅被限制为二叉树的有效成员,这是有道理的,但事实并非如此。

幸运的是,您不需要将Node 设为Comparable,您只需要将其value 设为Comparable

class Node<T: Comparable> {
    let value: T
    let left: Node<T>?
    let right: Node<T>?

    init(value: T, left: Node<T>? = nil, right: Node<T>? = nil) {
        self.value = value
        self.left = left
        self.right = right
    }
}

extension Node: Equatable {
    static func == (lhs: Node, rhs: Node) -> Bool {
        return lhs.value == rhs.value
            && lhs.left == rhs.left
            && lhs.right == rhs.right
    }
}

extension Node {
    func isBinarySubTree() -> Bool {
        return left.map { $0.value < self.value } ?? true
            && right.map { self.value < $0.value } ?? true
            && left?.isBinaryTree() ?? true
            && right?.isBinaryTree() ?? true
    }
}

【讨论】:

    【解决方案2】:

    感谢 Alexander,我的 EquatableComparable 搞混了!节点应该是

    class Node<T: Comparable> {
        //...
    }
    

    代码:

    let a = Node(value: 8)
    let b = Node(value: 7)
    
    let c = a.value > b.value
    

    必须工作,因为编译器知道值是Ints。但在函数中,输入值是未知的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 2012-11-16
      • 1970-01-01
      • 2017-06-07
      相关资源
      最近更新 更多