ios - 我们能否像在 Swift 中使用 Equatable 协议覆盖 operator == 一样覆盖 switch case 行为
问题描述
在开关情况下比较枚举时未调用 Equatable 协议,它如何比较值?
我在 Enum 下面实现了,它与 If 条件完美配合,但在 Switch case 中失败,switch case 如何比较 case 值?它在内部不使用 == 吗?
这是我的代码
import Foundation
public enum AMSelectionStyle{
case single
case multiple
case any
}
public enum AMCalenderMode{
case date
case time
case dateTime
case any
}
public enum AMNumberType:String{
case natural = "N" //(also called positive integers, counting numbers, or natural numbers); They are the numbers {1, 2, 3, 4, 5, …}
case whole = "W" //This is the set of natural numbers, plus zero, i.e., {0, 1, 2, 3, 4, 5, …}.
case integer = "Z" // This is the set of all whole numbers plus all the negatives (or opposites) of the natural numbers, i.e., {… , ⁻2, ⁻1, 0, 1, 2, …}
case rational = "Q" //This is all the fractions where the top and bottom numbers are integers; e.g., 1/2, 3/4, 7/2, ⁻4/3, 4/1 [Note: The denominator cannot be 0, but the numerator can be].
case real = "R" //(also called measuring numbers or measurement numbers). This includes all numbers that can be written as a decimal. This includes fractions written in decimal form e.g., 0.5, 0.75 2.35, ⁻0.073, 0.3333, or 2.142857. It also includes all the irrational numbers such as π, √2 etc. Every real number corresponds to a point on the number line.
case all = "" // all of the above
}
public enum AMInputType:Equatable {
case list(AMSelectionStyle)
case number(AMNumberType)
case calender(AMCalenderMode)
case freeText
case boolian
case picklist
public static func ==(lhs: AMInputType, rhs: AMInputType) -> Bool {
switch (lhs, rhs) {
case (let .list(a1), let .list(a2)):
if a1 == .any || a2 == .any {
return true
}else if a1 == .single && a2 == .single {
return true
}else if a1 == .multiple && a2 == .multiple {
return true
}
return a1 == a2
case (let .number(a1), let .number(a2)):
if a1 == .all || a2 == .all {
return true
}else if a1 == .natural && a2 == .natural {
return true
}else if a1 == .whole && a2 == .whole {
return true
}else if a1 == .integer && a2 == .integer {
return true
}else if a1 == .rational && a2 == .rational {
return true
}else if a1 == .real && a2 == .real {
return true
}
return a1 == a2
case (let .calender(a1), let .calender(a2)):
if a1 == .any || a2 == .any {
return true
}else if a1 == .date && a2 == .date {
return true
}else if a1 == .time && a2 == .time {
return true
}else if a1 == .dateTime && a2 == .dateTime {
return true
}
return a1 == a2
case (.freeText, .freeText):
return true
case (.boolian, .boolian):
return true
case (.picklist, .picklist):
return true
default:
return false
}
}
}
func compareEnum(inputType:AMInputType)->Bool{
switch inputType {
case .number(.all):
print("Switch case `number` check Successful")
return true
case .calender(.any):
print("Switch case `calender` check Successful")
return true
case .list(.any):
print("Switch case `list` check Successful")
return true
default:
print("Switch case check Failed")
return false
}
}
当枚举参数值与案例编号不同时比较失败
compareEnum(inputType: .number(.real))
当枚举参数值与案例编号相同时,比较成功。
compareEnum(inputType: .number(.all))
如果条件成功,则案例编号的不同枚举参数。
if AMInputType.number(.all) == AMInputType.number(.real) {
print("If Condition `number` check Successful")
}
编辑 1 - 根据@Tarun Tyagi 的建议转换枚举以实现 Equitable
问题仍然存在。在 Switch 案例中未调用公平协议
public enum AMSelectionStyle:Int, Equatable{
case single
case multiple
case any
public static func ==(lhs: AMSelectionStyle, rhs: AMSelectionStyle) -> Bool {
switch (lhs, rhs) {
case (.single, .single):
return true
case (.single, .multiple):
return false
case (.single, .any):
return true
case (.multiple, .multiple):
return true
case (.multiple, .single):
return false
case (.multiple, .any):
return true
case (.any, .any):
return true
case (.any, .single):
return true
case (.any, .multiple):
return true
}
}
}
public enum AMCalenderMode:Int, Equatable{
case date
case time
case dateTime
case any
public static func ==(lhs: AMCalenderMode, rhs: AMCalenderMode) -> Bool {
switch (lhs, rhs) {
case (.date, .date):
return true
case (.date, .time):
return false
case (.date, .dateTime):
return false
case (.date, .any):
return true
case (.time, .time):
return true
case (.time, .date):
return false
case (.time, .dateTime):
return false
case (.time, .any):
return true
case (.dateTime, .dateTime):
return true
case (.dateTime, .date):
return false
case (.dateTime, .time):
return false
case (.dateTime, .any):
return true
case (.any, .any):
return true
case (.any, .date):
return true
case (.any, .time):
return true
case (.any, .dateTime):
return true
}
}
}
public enum AMNumberType:String, Equatable{
case natural = "N" //(also called positive integers, counting numbers, or natural numbers); They are the numbers {1, 2, 3, 4, 5, …}
case whole = "W" //This is the set of natural numbers, plus zero, i.e., {0, 1, 2, 3, 4, 5, …}.
case integer = "Z" // This is the set of all whole numbers plus all the negatives (or opposites) of the natural numbers, i.e., {… , ⁻2, ⁻1, 0, 1, 2, …}
case rational = "Q" //This is all the fractions where the top and bottom numbers are integers; e.g., 1/2, 3/4, 7/2, ⁻4/3, 4/1 [Note: The denominator cannot be 0, but the numerator can be].
case real = "R" //(also called measuring numbers or measurement numbers). This includes all numbers that can be written as a decimal. This includes fractions written in decimal form e.g., 0.5, 0.75 2.35, ⁻0.073, 0.3333, or 2.142857. It also includes all the irrational numbers such as π, √2 etc. Every real number corresponds to a point on the number line.
case all = "" // all of the above
public static func ==(lhs: AMNumberType, rhs: AMNumberType) -> Bool {
switch (lhs, rhs) {
case (.natural, .natural):
return true
case (.natural, .whole):
return false
case (.natural, .integer):
return false
case (.natural, .rational):
return false
case (.natural, .real):
return false
case (.natural, .all):
return true
case (.whole, .whole):
return true
case (.whole, .natural):
return false
case (.whole, .integer):
return false
case (.whole, .rational):
return false
case (.whole, .real):
return false
case (.whole, .all):
return true
case (.integer, .integer):
return true
case (.integer, .natural):
return false
case (.integer, .whole):
return false
case (.integer, .rational):
return false
case (.integer, .real):
return false
case (.integer, .all):
return true
case (.rational, .rational):
return true
case (.rational, .natural):
return false
case (.rational, .whole):
return false
case (.rational, .integer):
return false
case (.rational, .real):
return false
case (.rational, .all):
return true
case (.real, .real):
return true
case (.real, .natural):
return false
case (.real, .whole):
return false
case (.real, .integer):
return false
case (.real, .rational):
return false
case (.real, .all):
return true
case (.all, .all):
return true
case (.all, .natural):
return true
case (.all, .whole):
return true
case (.all, .integer):
return true
case (.all, .rational):
return true
case (.all, .real):
return true
}
}
}
解决方案
只要所有案例(及其相关值)都Equatable
符合.enum
Equatable
所以默认情况下你会得到一个正确的实现,你只需要Equatable
在所有必要的地方做标记。
import Foundation
public enum AMSelectionStyle: Int, Equatable {
case single
case multiple
case any
}
public enum AMCalenderMode: Int, Equatable {
case date
case time
case dateTime
case any
}
public enum AMNumberType: String, Equatable {
case natural = "N"
case whole = "W"
case integer = "Z"
case rational = "Q"
case real = "R"
case all = ""
}
public enum AMInputType: Equatable {
case list(AMSelectionStyle)
case number(AMNumberType)
case calender(AMCalenderMode)
case freeText
case boolian
case picklist
}
如果你用上面的代码运行你的测试,一切都应该通过。无需为此实现您自己的代码。
更新
在进一步澄清之后,很明显像any
/这样的特殊情况all
需要在自定义实现中处理。综合实现不会处理这部分。
这是更新的实现 -
- 制作所有枚举
Equatable
,处理它们的特殊情况any
/all
在这些类型特定的实现中。 - 从包含其他枚举作为关联类型的最终枚举中,根据需要利用这些特定于类型的实现。
import Foundation
public enum AMSelectionStyle: Int, Equatable {
case single
case multiple
case any
public static func ==(lhs: Self, rhs: Self) -> Bool {
let any = Self.any.rawValue
if lhs.rawValue == any || rhs.rawValue == any {
return true
} else {
return lhs.rawValue == rhs.rawValue
}
}
}
public enum AMCalendarMode: Int, Equatable {
case date
case time
case dateTime
case any
public static func ==(lhs: Self, rhs: Self) -> Bool {
let any = Self.any.rawValue
if lhs.rawValue == any || rhs.rawValue == any {
return true
} else {
return lhs.rawValue == rhs.rawValue
}
}
}
public enum AMNumberType: String, Equatable {
case natural = "N"
case whole = "W"
case integer = "Z"
case rational = "Q"
case real = "R"
case all = ""
public static func ==(lhs: Self, rhs: Self) -> Bool {
let all = Self.all.rawValue
if lhs.rawValue == all || rhs.rawValue == all {
return true
} else {
return lhs.rawValue == rhs.rawValue
}
}
}
public enum AMInputType: Equatable {
case list(AMSelectionStyle)
case number(AMNumberType)
case calendar(AMCalendarMode)
case freeText
case boolean
case picklist
public static func ==(lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case (.list(let l1), .list(let l2)): return l1 == l2
case (.number(let n1), .number(let n2)): return n1 == n2
case (.calendar(let c1), .calendar(let c2)): return c1 == c2
case (.freeText, .freeText),
(.boolean, .boolean),
(.picklist, .picklist): return true
default: return false
}
}
}
测试
var lhs: AMInputType = .number(.all)
var rhs: AMInputType = .number(.real)
print(lhs == rhs) // prints true
推荐阅读
- windows - 在 Windows WSL2 上构建 pyodide
- c++ - 带有 Netbeans 错误的 SFML:未定义对“sf::microseconds(long long)”的引用
- python - 基于列表展开数据框后如何在每个列表中获得元素的排名
- python - 查找出现在 numpy 数组中特定元素之后的元素
- reactjs - 并非所有 Bootstrap 类都适用于 React 应用程序
- python - 如何从常微分方程的解中创建图网络(Networkx)?
- javascript - 如何在 Truffle 部署期间添加 MinterRole?
- tensorflow-lite - 如何从 tensorflowlite 解释器中检索图像输出
- html - 理解父子元素——CSS
- javascript - 等待循环结束以继续函数并返回对象