Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
519 views
in Technique[技术] by (71.8m points)

enums - Can associated values and raw values coexist in Swift enumeration?

There are examples on Swift book demonstrating associated values and raw values separately, is there a way to define enums with the two features together?

I have tried to combine them, but got errors:

enum Barcode :String {
    case UPCA(Int, Int, Int) = "Order 1" // Enum with raw type cannot have cases with arguments
    case QRCode(String) = "Order 2" // Enum with raw type cannot have cases with arguments
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes this is possible. An enum may contain both associated values and raw values. (Swift 5 & 4)

Shorthand notation

The issue with your code is that you are using the shorthand notation for RawRepresentable and defining associated types.

Let's look at how to define these separately:

1) RawRepresentable (shorthand notation):

enum Barcode: String {
    case UPCA   = "order 1"
    case QRCode = "order 2"
}

2) Associated types:

enum Barcode {
    case UPCA(Int, Int, Int)
    case QRCode(String)
}

Each of these is great, but what if you need both as your code snippet shows.

Solution

Define the enum with associated values and then implement conformance to RawRepresentable separately in an extension (i.e. not using shorthand notation).

Example:

enum Barcode {
    case UPCA(Int, Int, Int)
    case QRCode(String)
}

extension Barcode: RawRepresentable {

    public typealias RawValue = String

    /// Failable Initalizer
    public init?(rawValue: RawValue) {
        switch rawValue {
        case "Order 1":  self = .UPCA(1,1,1) 
        case "Order 2":  self = .QRCode("foo")
        default:
            return nil
        } 
    }

    /// Backing raw value
    public var rawValue: RawValue {
        switch self {
        case .UPCA:     return "Order 1"
        case .QRCode:   return "Order 2"
        }
    }

}

Minor Detail

In this solution, defaults for the associated values, e.g. .UPCA(1,1,1) must be supplied when constructing the enum from the rawValue argument. You can get fancy and use the associated types as part of the backing raw value — which is more powerful, but adds some complexity.

References

For more info on the topic see Ole Begemann's excellent write up.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...