swift - Swift 中的枚举和泛型
问题描述
已编辑
您好,我正在尝试制作自己的单位转换器
但是当我尝试同时制作重量和长度时出现了一些问题
有很多重复的代码
enum LengthUnit: String{
case inch
case cm
case m
case yard
static func unit(of value: String) -> LengthUnit?{
switch value {
case let value where value.contains("inch"):
return .inch
case let value where value.contains("cm"):
return .cm
case let value where value.contains("m"):
return .m
case let value where value.contains("yard"):
return .yard
default:
return nil
}
}
}
enum WeightUnit:String {
case g
case kg
case lb
case oz
static func unit(of value: String) -> WeightUnit?{
switch value {
case let value where value.contains("g"):
return .g
case let value where value.contains("kg"):
return .kg
case let value where value.contains("lb"):
return .lb
case let value where value.contains("oz"):
return .oz
default:
return nil
}
}
}
不仅从String
函数中获取单位,而且还有许多相关的函数进行转换,有重复的代码
所以我尝试通过泛型来实现它,但我对此一无所知
如何为这两种 Unit 类型使用枚举和泛型
解决方案
由于您从您那里继承了您的枚举,因此您将免费String
获得init?(rawValue: String)
解析初始化程序。就个人而言,我不会创建类似的函数,unit(of:)
因为它只是丢弃了数量部分。相反,我会创建解析函数,如parse(value: String) -> (Double, LengthUnit)?
无论如何,如果您真的想要unit(of:)
功能并希望尽可能减少代码重复,您可能确实会从使用泛型中受益。
首先,我们需要Unit
像这样的标记协议
protocol UnitProtocol { }
然后,我们可以创建通用函数,该函数将使用init?(rawValue: String)
sRawRepresentable
Unit
根据传递的字符串返回单位
func getUnit<U: UnitProtocol & RawRepresentable>(of value: String) -> U? where U.RawValue == String {
// you need better function to split amount and unit parts
// current allows expressions like "15.6.7.1cm"
// but that's question for another topic
let digitsAndDot = CharacterSet(charactersIn: "0123456789.")
let unitPart = String(value.drop(while: { digitsAndDot.contains($0.unicodeScalars.first!) }))
return U.init(rawValue: unitPart)
}
基本上就是这样。如果你不喜欢使用函数而更喜欢静态方法,那么你只需要添加这些方法并getUnit(of:)
在里面调用
enum LengthUnit: String, UnitProtocol {
case inch
case cm
case m
case yard
static func unit(of value: String) -> LengthUnit? {
return getUnit(of: value)
}
}
enum WeightUnit: String, UnitProtocol {
case g
case kg
case lb
case oz
static func unit(of value: String) -> WeightUnit? {
return getUnit(of: value)
}
}
或者,unit(of:)
在任何地方添加方法,我们甚至可以做得更好并添加扩展
extension UnitProtocol where Self: RawRepresentable, Self.RawValue == String {
static func unit(of value: String) -> Self? {
return getUnit(of: value)
}
}
现在,您只需添加与和unit(of:)
的一致性即可免费获得静态String
Unit
enum WeightUnit: String, UnitProtocol {
case g
case kg
case lb
case oz
}
推荐阅读
- r - 使用 Tidyverse Join 更新/替换 Dataframe 中的值
- python - pip 和 conda 安装相同的包而不识别重复
- laravel - 一种清理 laravel 的方法
- javascript - 仅在 html 代码中使用 javascript 重新加载特定页面一次
- c - 如何计算两个字符串之间共有的不同字符的数量?
- shell - 检查系统上是否信任某个根 CA
- node.js - POST 无法使用 express + bootstrap 模式工作
- python - 图像旋转未按预期工作
- javascript - 实现 CSS Sidenav 独立
- c++ - 不能从回调中永久更改类的状态