Search code examples
swift3xcode8

Error: not conform to protocol 'Equatable'


I'm new to swift and following a tutorial to learn more.

In The following code, I have defined custom operators (< and ==) and however the code works fine but Xcode shows these errors in the 1st line of code.

Type 'SuitedCard' does not conform to protocol 'Equatable'
Type 'SuitedCard' does not conform to protocol 'Comparable'

here is the code:

struct SuitedCard: Equatable, Comparable {

    // a card can be ♥️, ♣️, ♦️, ♠️
    enum Suit {
        case hearts
        case spades
        case diamonds
        case clubs
    }

    // the possible values of a card
    enum Value: Int {
        case two = 2
        case three = 3
        case four = 4
        case five = 5
        case six = 6
        case seven = 7
        case eight = 8
        case nine = 9
        case ten = 10
        case jack = 11
        case queen = 12
        case king = 13
        case ace = 14
    }

    // properties
    let suit: Suit
    let value: Value
    var isFaceDown: Bool
}

var valueArray: [SuitedCard.Value] = [.ten, .jack, .queen, .king]


func ==(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
    for cardValue in valueArray {
        if lhs.value == cardValue {
            for cardValue2 in valueArray {
                if rhs.value == cardValue2 {
                    return true
                }
            }
        }
    }
    if lhs.value == rhs.value {
        return true
    }
    return false
}

func <(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
    var lhsRawValue: Int
    var rhsRawValue: Int
    if lhs.value == .jack || lhs.value == .queen || lhs.value == .king {
        lhsRawValue = 10
    } else {
        lhsRawValue = lhs.value.rawValue
    }
    if rhs.value == .jack || rhs.value == .queen || rhs.value == .king {
        rhsRawValue = 10
    } else {
        rhsRawValue = rhs.value.rawValue
    }
    return lhsRawValue < rhsRawValue
}

let smaller = SuitedCard(suit: .hearts, value: .five, isFaceDown: true)

let bigger = SuitedCard(suit: .diamonds, value: .six, isFaceDown: false)

smaller >= smaller

smaller < bigger

What's wrong?


Solution

  • In Swift 3, operators required for protocols are declared as static members.

    One way to work with such protocols is moving your operator definitions into the struct as static member:

    struct SuitedCard: Comparable { //### Comparable implies Equatable
    
        //...
    
        // function for custom operator ==
        static func ==(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
            //...
            return false
        }
        // function for custom operator <
        static func <(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
            //...
            return false
        }
    }
    

    Another way, you can declare the conformance to the protocol using extension:

    struct SuitedCard {
    
        //...
    }
    
    // function for custom operator ==
    func ==(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
        //...
        return false
    }
    // function for custom operator <
    func <(lhs: SuitedCard, rhs: SuitedCard) -> Bool {
        //...
        return false
    }
    
    extension SuitedCard: Comparable {}