Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift中的枚举和泛型_Swift_Generics_Enums - Fatal编程技术网

Swift中的枚举和泛型

Swift中的枚举和泛型,swift,generics,enums,Swift,Generics,Enums,已编辑 你好,我想做我自己的单位转换器 但是,当我试图同时增加体重和长度时,出现了一些问题 有那么多重复的代码 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.c

已编辑

你好,我想做我自己的单位转换器

但是,当我试图同时增加体重和长度时,出现了一些问题

有那么多重复的代码

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
函数中获取单位,而且还有许多用于转换的关联函数,其中存在重复的代码

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
        }
    }
}
所以我尝试用泛型来实现它,但我对此一无所知


如何将枚举和泛型用于这两种单元类型

由于此处枚举项的原始值是枚举项的字符串版本,因此LengthUnit.inch-->“inch”

更新

包含删除字符串数字部分示例的更新版本。如果不知道需要什么样的数据,就很难知道最佳解决方案是什么

extension String {
    var lengthUnit: LengthUnit? {
        get {
            let string = self.trimmingCharacters(in: CharacterSet(charactersIn: "01234567890."))
           return LengthUnit(rawValue:string)
        }
    }
}
注释:由于您正在创建一个单位转换器,因此您需要在某个时刻将字符串拆分为值和单位,以便能够执行转换,因此首先使用我的原始版本可能更明智


注释2:我不知道如何在这里使用泛型,您的输入总是一个字符串,我认为让函数/属性返回泛型没有好处。您可以只使用一个
单元
枚举简化设计,然后只使用一个
单元
属性而不是两个

,因为您从
字符串
继承了枚举,您将获得
init?(rawValue:String)
免费解析初始值设定项。就我个人而言,我不会创建像
unit(of:)
这样的函数,因为它只是丢掉了amount部分。相反,我将创建解析函数,如
parse(value:String)->(Double,LengthUnit)

无论如何,如果您真的想要
unit(of:)
函数,并希望尽可能减少代码重复,那么使用泛型确实会让您受益匪浅

首先,我们需要这样的
Unit
marker协议

protocol UnitProtocol { }
然后,我们可以创建泛型函数,它将使用
rawrrepresentable的
init?(rawValue:String)
返回基于传递字符串的单位

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)
}
或者,在任何地方添加
unit(of:)
方法,我们甚至可以做得更好并添加扩展

extension UnitProtocol where Self: RawRepresentable, Self.RawValue == String {
    static func unit(of value: String) -> Self? {
        return getUnit(of: value)
    }
}
现在,只需将一致性添加到
String
unit
中,您就可以免费获得静态
unit(of:)

enum WeightUnit: String, UnitProtocol {
    case g
    case kg
    case lb
    case oz
}

只要“单位案例名称”等于“单位字符串表示法”@DongkunLeeI编辑了我的问题代码。输入将是“15cm”或“15oz”我想消除重复的代码。您不能像在代码中那样使用
contains
,因为例如
15kg
将被转换为
15weightUnit.g
,所以您需要在获取
单位
属性之前或时将字符串拆分为值和单位。这就是我想要的!!谢谢
enum WeightUnit: String, UnitProtocol {
    case g
    case kg
    case lb
    case oz
}