Binary operator '==' cannot be applied to two operands

微笑、不失礼 提交于 2021-02-06 14:59:17

问题


I have a class with the protocol Equatable. The class looks like this:

class Item: Equatable {

    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}

func ==(lhs: Item, rhs: Item) -> Bool {
    return lhs.item == rhs.item
}

But this is giving me the error (see title). The property item was [[String: String]] before and there was no problem and I have no idea how to fix this. I tried googling and searching all over SO but with no luck..

The enum is just a simple basic one:

enum Modifications: Int {
    case Add    = 1
    case Remove = 2
    case More   = 3
    case Less   = 4
}

回答1:


Update: SE-0143 Conditional conformances has been implemented in Swift 4.2.

As a consequence, your code does compile now. And if you define Item as a struct

struct Item: Equatable {
    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}

then the compiler synthesizes the == operator automatically, compare SE-0185 Synthesizing Equatable and Hashable conformance


(Pre Swift 4.1 answer:)

The problem is that even if == is defined for the dictionary type [Modifications: String], that type does not conform to Equatable. Therefore the array comparison operator

public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool

cannot be applied to [[Modifications: String]].

A possible concise implementation of == for Item would be

func ==(lhs: Item, rhs: Item) -> Bool {
    return lhs.item.count == rhs.item.count 
           && !zip(lhs.item, rhs.item).contains {$0 != $1 }
}

Your code compiles for [[String: String]] – if the Foundation framework is imported, as @user3441734 correctly said – because then [String: String] is automatically converted to NSDictionary which conforms to Equatable. Here is a "proof" for that claim:

func foo<T : Equatable>(obj :[T]) {
    print(obj.dynamicType)
}

// This does not compile:
foo( [[Modifications: String]]() )

// This compiles, and the output is "Array<NSDictionary>":
foo( [[String: String]]() )



回答2:


In your == function for Item objects, you need to specify further how to compare two types of arrays of dictionaries (specifically, two types of [[Modifications: String]]).

The following working solution compares your item arrays element by element (dictionary by dictionary), and == returns true only if the arrays contain the same number of dictionaries, and if all entries are alike and ordered the same fashion in the array of dictionares

func ==(lhs: Item, rhs: Item) -> Bool {

    if lhs.item.count == rhs.item.count {
        for (i, lhsDict) in lhs.item.enumerate() {
            if lhsDict != rhs.item[i] {
                return false
            }
        }
        return true
    }
    else {
        return false
    }
}

class Item : Equatable {

    let item: [[Modifications: String]]

    init(item: [[Modifications: String]]) {
        self.item = item
    }
}

You probably want to modify this into the form you actually want to use for comparison, but I hope you get the gist of it.

Note also that, if testing this in a playground, it's important that your == function definition func ==(lhs: Item, rhs: Item) -> Bool { .. should precede your class definition, otherwise you will get an error of nonconformance to Equatable.



来源:https://stackoverflow.com/questions/34640685/binary-operator-cannot-be-applied-to-two-operands

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!