【问题标题】:Swift Enum: Expression pattern matching issueSwift Enum:表达式模式匹配问题
【发布时间】:2019-10-08 00:51:50
【问题描述】:

我一直在尝试将自定义关联值与枚举中的字符串混合,但无法这样做。当我尝试在枚举上应用 switch case 时,我收到此错误:'Fruit' 类型的表达式模式无法匹配'Fruit' 类型的值

是不是因为字符串是值类型,因此 Swift 可以比较它们,但不能比较作为引用类型的 Fruit 的自定义类对象?

class Fruit{
    let name: String?
    let energyKcl: Double?
    let costPerKg: Double?

    init(name:String, energyKcl: Double, costPerKg: Double) {
        self.name = name
        self.energyKcl = energyKcl
        self.costPerKg = costPerKg
    }
}

enum Calorie {
    case fruit(Fruit)
    case chocolate (String)
    case dairy(String)
    case Nuts(String)
}


let banana = Fruit.init(name: "Banana", energyKcl: 100, costPerKg: 10)

func prepareBreakfast(calories: Calorie){
    switch calories {

    case .chocolate("Dark"):
        print("Dark")

    case .chocolate("White"):
        print("White")

    case .fruit(banana): //Error: Expression pattern of type 'Fruit' cannot match values of type 'Fruit'
        print("banana")

    default:
        print ("Not available")
    }
}

prepareBreakfast(calories: .fruit(banana))

【问题讨论】:

  • 类型应该是Equatable 用于模式匹配。
  • 我不确定Calorie 背后的想法是什么,但看起来它更适合建模为具有多个符合类的协议。这个枚举看起来像是您希望将来能够扩展的那种东西,而多态性比在任何使用它的地方都添加新的 switch case 做得更好。
  • 不相关但为什么所有属性都是可选的?它们是常量,并且清楚地使用非可选值进行了初始化。即使没有问号,代码也可以编译。如果Fruit 是一个结构并采用Equatable,您将免费获得== 运算符

标签: swift enums


【解决方案1】:

没有问题,如果没有 Equatable 协议,自定义类是无法比较的

extension Fruit: Equatable {

    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.name == rhs.name
        && lhs.energyKcl == rhs.energyKcl
        && lhs.costPerKg == rhs.costPerKg
    }

}

【讨论】:

    【解决方案2】:

    模式匹配在内部使用Equatable,所以你应该改变你的Fruit类:

    extension Fruit: Equatable {
        static func == (lhs: Fruit, rhs: Fruit) -> Bool {
            return lhs.name == rhs.name // or every field if you want
        }
    }
    

    如果您想使用引用,只需将 == 函数更改为在两个引用相等时返回 true,但我认为这不是一个好主意:

    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs === rhs
    }
    

    【讨论】:

      【解决方案3】:

      在您的代码中,

      替换prepareBreakfast(calories:)方法中的下面一行,

      case .fruit(banana):
      

      case .fruit(let banana):
      

      你可以走了。我认为您的代码没有任何其他问题。它在我的最后工作得很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-09
        • 1970-01-01
        • 2011-07-17
        • 1970-01-01
        相关资源
        最近更新 更多