Swift 为什么有关联值的枚举不能设置RawValue?

通常的枚举

先看看一般语意下的Enum 的标识

enum SeasonI: Int {
    case summer
    case spring
    case winter
}

SeasonI.summer.rawValue  /// 0

在 Swift 中也可以和 OC 一样,设置这样简单的 Enum, 前提是指定为 Int 类型。

可扩展的枚举

enum SeasonS: String {
    case summer
    case spring
    case winter
}
SeasonS.summer.rawValue  /// 'summer'

可以看到 Swift 中 Enum 除了可以支持 Int 类型,还支持其他类型.

rawValue 到底是什么?

在讲 rawValue 之前先要讲RawValue, 首先 RawValue 是一个关联类型,例如如果一个类型是Int,则关联类型是 Int, 是 String 则关联对象是 String.

rawValue 的定义:

在Swift 源码 CompilerProtocols.swift 里面是有如下的定义:

public protocol RawRepresentable {
  /// The raw type that can be used to represent all values of the conforming
  /// type.
  ///
  /// Every distinct value of the conforming type has a corresponding unique
  /// value of the `RawValue` type, but there may be values of the `RawValue`
  /// type that don't have a corresponding value of the conforming type.
  associatedtype RawValue

  /// Creates a new instance with the specified raw value.
  ///
  /// If there is no value of the type that corresponds with the specified raw
  /// value, this initializer returns `nil`. For example:
  ///
  ///     enum PaperSize: String {
  ///         case A4, A5, Letter, Legal
  ///     }
  ///
  ///     print(PaperSize(rawValue: "Legal"))
  ///     // Prints "Optional("PaperSize.Legal")"
  ///
  ///     print(PaperSize(rawValue: "Tabloid"))
  ///     // Prints "nil"
  ///
  /// - Parameter rawValue: The raw value to use for the new instance.
  init?(rawValue: RawValue)

  /// The corresponding value of the raw type.
  ///
  /// A new instance initialized with `rawValue` will be equivalent to this
  /// instance. For example:
  ///
  ///     enum PaperSize: String {
  ///         case A4, A5, Letter, Legal
  ///     }
  ///
  ///     let selectedSize = PaperSize.Letter
  ///     print(selectedSize.rawValue)
  ///     // Prints "Letter"
  ///
  ///     print(selectedSize == PaperSize(rawValue: selectedSize.rawValue)!)
  ///     // Prints "true"
  var rawValue: RawValue { get }
}

也就是说任何遵循 RawRepresentable 的对象, 都是可以使用 rawValue 的。

有关联值的 Enum

enum SeasonWithAssociatedValue {
    case summer
    case spring
    case winter
    case autumn(country: String)
}

总结

  1. 有关联值的 Enum 是没有对应的关联类,因为关联值的存在,所以不能统一关联类型。
  2. 没有关联类型,也就没有实现 RawRepresentable , 相应的也就没有了 rawValue。
  3. 那如何实现类似的功能呢?
/// Extension
extension SeasonWithAssociatedValue {
     var rawDescription: String {
        switch self {
        case .summer:
            return "Summer"
        case .autumn(_):
            return "Autumn"
        default:
            return "Other"
        }
    }
}

SeasonWithAssociatedValue.autumn(country: " ").rawDescription
© 著作权归作者所有
这个作品真棒,我要支持一下!
主要会讲跟 iOS 相关的 Swift,JS,dart,OC 语言层面的一些事情,有些特性可能会被我们忽略,但语言...
0条评论
top Created with Sketch.