web-dev-qa-db-fra.com

L'opérateur binaire '==' ne peut pas être appliqué à deux opérandes

J'ai une classe avec le protocole Equatable. La classe ressemble à ceci:

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
}

Mais cela me donne l'erreur (voir titre). La propriété item était [[String: String]] avant et il n'y a eu aucun problème et je n'ai aucune idée de comment résoudre ce problème. J'ai essayé de googler et de chercher partout SO mais sans chance ..

L'énumération est juste une simple base:

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

Mise à jour: SE-0143 Conformités conditionnelles a été implémenté dans Swift 4.2.

Par conséquent, votre code se compile maintenant. Et si vous définissez Item comme un struct

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

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

alors le compilateur synthétise le == opérateur automatiquement, comparer SE-0185 Synthétiser la conformité Equatable et Hashable


(Pre Swift 4.1 réponse:)

Le problème est que même si == est défini pour le type de dictionnaire [Modifications: String], ce type n'est pas conforme à Equatable. Par conséquent, l'opérateur de comparaison de tableau

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

ne peut pas être appliqué à [[Modifications: String]].

Une possible mise en œuvre concise de == pour Item serait

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

Votre code compile pour [[String: String]] - si le framework Foundation est importé, comme @ user3441734 l'a correctement dit - car alors [String: String] est automatiquement converti en NSDictionary qui est conforme à Equatable. Voici une "preuve" pour cette affirmation:

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]]() )
19
Martin R

Dans votre fonction == Pour les objets Item, vous devez préciser davantage comment comparer deux types de tableaux de dictionnaires (en particulier, deux types de [[Modifications: String]]).

La solution de travail suivante compare vos item tableaux élément par élément (dictionnaire par dictionnaire) et == Renvoie vrai uniquement si les tableaux contiennent le même nombre de dictionnaires et si toutes les entrées sont identiques - et ordonné de la même façon dans le tableau des dictionnaires

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
    }
}

Vous voudrez probablement le modifier dans le formulaire que vous souhaitez réellement utiliser pour la comparaison, mais j'espère que vous en aurez l'essentiel.

Notez également que si vous testez cela dans une aire de jeux, il est important que votre définition de fonction ==func ==(lhs: Item, rhs: Item) -> Bool { .. --- précède la définition de votre classe, sinon vous obtiendrez une erreur de non-conformité à Equatable.

3
dfri