在使用if语句匹配枚举时出现错误

7

我在使用枚举时遇到了一个问题,但我无法理解它。

这是一个枚举类型的声明:

enum SomeType {
    case un
    case deux
    case trois
}

接下来我想用一个if语句匹配枚举类型中的单个值:

var testValue: SomeType = .trois

if testValue == .trois {
    // Do something
}

一切都好!

现在我想仅将关联值添加到第一个成员值中:

enum SomeType {
    case un(Int)
    case deux
    case trois
}

var testValue: SomeType = .trois

if testValue == .trois {
    // Do something
}

if语句中出现错误:无法找到成员'trois'

这是否意味着只能使用switch语句匹配枚举?

说明
我想实现的是:"testValue是否是'trois'成员值,不考虑关联值"。换句话说,如何仅基于成员值匹配枚举。

以下是实现Airspeed Velocity答案的解决方案:

// Test equality only on member value
func == (lhs:SomeType, rhs:SomeType) -> Bool {
    switch (lhs, rhs) {
    case (.un(let lhsNum), .un(let rhsNum)):return true
    case (.deux, .deux): return true
    case (.trois, .trois): return true
    default: return false
    }
}

// Test equality on member value AND associated value
func === (lhs:SomeType, rhs:SomeType) -> Bool {
    switch (lhs, rhs) {
    case (.un(let lhsNum), .un(let rhsNum)) where lhsNum == rhsNum: return true
    case (.deux, .deux): return true
    case (.trois, .trois): return true
    default: return false
    }
}

var testValue = SomeType.un(3)


// Tests

if testValue == .un(1) {
    println("Same member value")
}


if testValue === .un(3) {
    println("Same member value AND same associated contents")
}
1个回答

9
没有关联类型的枚举自动具有可比性。而有关联类型的枚举则没有可比性。这是因为只有您自己知道如何处理关联类型(例如随您的.un值一起传递的整数)。即使.trois没有关联类型,缺乏免费的可比性也会影响整个枚举。Switch 的工作方式略有不同,它使用模式匹配,因此仍然有效。
如果您希望具有关联类型的枚举具有可比性,则可以定义自己的==运算符:
enum SomeType {
    case un(Int)
    case deux
    case trois
}

// possibly there's a more succinct way to do this switch
func ==(lhs: SomeType, rhs: SomeType) -> Bool {
    switch (lhs,rhs) {
    case let (.un(i), .un(j)) where i == j: return true
    case (.deux,.deux): return true
    case (.trois, .trois): return true
    default: return false
    }
}

var testValue: SomeType = .trois

if testValue == .trois {
    println("equals .trois")
}

// note, for SomeType to work with generic
// functions that require Equatable, you have
// to add that too:
extension SomeType: Equatable { }

// which means this will work:
let a: [SomeType] = [.un(1), .deux, .trois]
find(a, .trois)

好的,谢谢。我理解为测试是在成员值而不是成员值+相关值上进行的。有点像:“如果成员值相同”。这是Ada语言的一些旧反应! - Dominique Vial
经过一些思考,你的答案并不是我想要达到的。我需要知道一个变量是否匹配给定的成员值:无需考虑关联值。换句话说:“这个变量的成员值是否等于那个值”。 - Dominique Vial
所以你的意思是说,无论它们的关联值是否相等,你希望两个 SomeType.un 相等?如果是这样,只需在定义 == 时从 switch 中删除 where 子句(即对 .un 做与 .deux.trois 相同的处理)。但是你仍然需要自己定义 ==,因为 Swift 需要知道这是你想要的行为。 - Airspeed Velocity
是的,那就是我想做的。我已经尝试过了,它运行得很好。也许还可以定义 === 来包括关联值。 - Dominique Vial
@Domsware,你写这个已经有一段时间了,但我认为你应该避免使用===,因为它在Swift中已经用于其他用途。 - Pop Flamingo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接