Home Articles

如何通过忽略Swift中的关联值来比较枚举与关联值?

Asked
Viewed 163 times
59

阅读How to test equality of Swift enums with associated values后,我实现了以下枚举:

enum CardRank {
    case Number(Int)
    case Jack
    case Queen
    case King
    case Ace
}

func ==(a: CardRank, b: CardRank) -> Bool {
    switch (a, b) {
    case (.Number(let a), .Number(let b))   where a == b: return true
    case (.Jack, .Jack): return true
    case (.Queen, .Queen): return true
    case (.King, .King): return true
    case (.Ace, .Ace): return true
    default: return false
    }
}

以下代码有效:

let card: CardRank = CardRank.Jack
if card == CardRank.Jack {
    print("You played a jack!")
} else if card == CardRank.Number(2) {
    print("A two cannot be played at this time.")
}

但是,这不编译:

let number = CardRank.Number(5)
if number == CardRank.Number {
    print("You must play a face card!")
}

...并且它给出以下错误消息:

二进制运算符'=='不能应用于'CardRank'和'(Int) - > CardRank'类型的操作数

我'm assuming this is because it'期待完整类型而 CardRank.Number 没有指定整个类型,而 CardRank.Number(2) 则没有 . 但是,在这种情况下,我希望它匹配 any 数字;不只是一个特定的 .

显然我可以使用switch语句,但实现 == 运算符的重点是避免这个冗长的解决方案:

switch number {
case .Number:
    print("You must play a face card!")
default:
    break
}

有没有办法比较枚举与关联值而忽略其相关值?

Note: 我意识到我可以将 == 方法中的情况更改为 case (.Number, .Number): return true ,但是,虽然它会正确返回true,但我的比较仍然看起来像是与特定数字( number == CardRank.Number(2) ;其中2是虚拟值)进行比较而不是任何数字( number == CardRank.Number ) .

4 Answers

  • 59

    Edit: 正如Etan指出的那样,您可以省略 (_) 通配符匹配以更干净地使用它 .


    不幸的是,我比在Swift 1.2中使用't believe that there'方法更容易 .

    但是,在Swift 2中,您可以使用新的 if-case 模式匹配:

    let number = CardRank.Number(5)
    if case .Number(_) = number {
        // Is a number
    } else {
        // Something else
    }
    

    如果您希望避免冗长,可以考虑在实现switch语句的枚举中添加 isNumber computed属性 .

  • 19

    在Swift 4.2中,如果所有关联值都符合 Equatable ,则将合成 Equatable . 您需要做的就是添加 Equatable .

    enum CardRank: Equatable {
        case Number(Int)
        case Jack
        case Queen
        case King
        case Ace
    }
    

    https://developer.apple.com/documentation/swift/equatable?changes=_3

  • 6

    不幸的是在Swift 1.x中没有其他方法,所以你必须使用 switch ,这是_1848609的版本,你可以使用 if case

    if case .Number = number {
        //ignore the value
    }
    if case .Number(let x) = number {
        //without ignoring
    }
    
  • 2

    这是一个更简单的方法:

    enum CardRank {
        case Two
        case Three
        case Four
        case Five
        case Six
        case Seven
        case Eight
        case Nine
        case Ten
        case Jack
        case Queen
        case King
        case Ace
    
        var isFaceCard: Bool {
            return (self == Jack) || (self == Queen) || (self == King)
        }
    }
    

    不需要重载==运算符,检查卡类型不需要混淆语法:

    let card = CardRank.Jack
    
    if card == CardRank.Jack {
        print("You played a jack")
    } else if !card.isFaceCard {
        print("You must play a face card!")
    }
    

Related