枚举符合RawRepresentable协议

11
在Swift书中,枚举示例运行良好。
enum CompassPoint: String {
    case north, south, east, west
}

var northCom = CompassPoint.north
print (northCom)

然而我想使用一个可失败的初始化程序,因此做了一个例子。

enum WeekDay: String {
    case monday, tuesday, wednesday, thursday, friday
    init?(rawValue: Int){
        switch rawValue {
        case 0 : self = .monday
        case 1 : self = .tuesday
        case 2 : self = .wednesday
        case 3 : self = .thursday
        case 4 : self = .friday
        default : return nil
        }
    }
}

并且收到一个错误,指出Weekday不符合RawRepresentable的要求 - 尽管我觉得编译器应该自动合成这个遵从性,所以不明白为什么这不能编译。

我做了什么 创建了一个类似的工作示例(以查看问题所在),并仍然希望使用具有可失败初始化程序的枚举来遵从RawRepresentable。 我在Swift书中找不到此示例,在Stack Overflow问题或更广泛的互联网上也找不到。

我提供的内容 上面给出了一个完整的示例,以及我期望的行为的工作示例和发生错误的代码。

没有帮助的内容 通过链接或评论引用Swift书籍是没有帮助的,因为我已经从中取得了一个示例。我想在该示例的基础上使用具有可失败初始化程序的枚举。 不使用枚举或可失败初始化程序也没有帮助。 这个问题涉及到使用具有可失败初始化程序的枚举,并遵守RawRepresentable。 这不是作业,但这些都是我的学习约束,并且我对结果感兴趣。

问题是 如何在与非工作示例相同的情况下使用具有可失败初始化程序的枚举?

3个回答

15

显然您对于init?(rawValue: Int)的定义阻止了编译器自动推断出RawValue类型。添加一个类型别名可以解决:

enum WeekDay: String {
    typealias RawValue = String

    case monday, tuesday, wednesday, thursday, friday

    init?(rawValue: Int){
        switch rawValue {
        case 0 : self = .monday
        case 1 : self = .tuesday
        case 2 : self = .wednesday
        case 3 : self = .thursday
        case 4 : self = .friday
        default : return nil
        }
    }
}

或者使用不同的参数名称定义您自己的自定义初始化函数:

enum WeekDay: String {

    case monday, tuesday, wednesday, thursday, friday

    init?(rawInt: Int){
        switch rawInt {
        case 0 : self = .monday
        case 1 : self = .tuesday
        case 2 : self = .wednesday
        case 3 : self = .thursday
        case 4 : self = .friday
        default : return nil
        }
    }
}

1
我现在可以看到,只需要称其为索引 - 我从 use your loaf 看到的 - https://useyourloaf.com/blog/enum-raw-values-and-failable-initializers/ - WishIHadThreeGuns

4

虽然我认为合规性应该由编译器合成

是的,这里你的rawValue的类型是String,而不是Int。只需像这样创建您的枚举:

enum WeekDay: String {
    case monday, tuesday, wednesday, thursday, friday
}

然后按照以下方式创建一个名为WeekDay的对象:
let monday: WeekDay? = WeekDay(rawValue: "monday")
let notADay: WeekDay? = WeekDay(rawValue: "foo")

当然,您也可以添加一个带整数参数的自定义初始化函数:
enum WeekDay: String {
    case monday, tuesday, wednesday, thursday, friday
    init?(integer: Int){
        switch integer {
        case 0 : self = .monday
        case 1 : self = .tuesday
        case 2 : self = .wednesday
        case 3 : self = .thursday
        case 4 : self = .friday
        default : return nil
        }
    }
}

并创建您的weekDay,如下所示:
let monday: WeekDay? = WeekDay(integer: 0)
let notADay: WeekDay? = WeekDay(integer: 30)

1

从Swift 5开始,除了自动生成的init?(rawValue: String)之外,再次拥有第二个init?(rawValue: Int)不会出现错误。但如果您想覆盖RawRepresantable实现并使rawValue成为Int,这是可能的。

extension WeekDay : RawRepresentable {
    
    typealias RawValue = Int
    init?(rawValue: Int){
        switch rawValue {
        case 0 : self = .monday
        case 1 : self = .tuesday
        case 2 : self = .wednesday
        case 3 : self = .thursday
        case 4 : self = .friday
        default : return nil
        }
    }
    
    var rawValue: Int {
        switch self {
        case .monday : return 0
        case .tuesday :  return 1
        case .wednesday : return 2
        case .thursday : return 3
        case .friday : return 4
        }
    }
}
print(WeekDay.init(rawValue: 2)) // Optional(WeekDay.wednesday)
print(WeekDay.RawValue.self) // Int

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