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

1. 一般枚举

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

enum Score: Int {
    case Ag
    case Bg
    case Cg
}

Score.Ag.rawValue  /// 0

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

2. 可扩展的枚举

enum ScoreStr: String {
    case Ag
    case Bg
    case Cg
}
ScoreStr.Ag.rawValue  /// 'Ag'

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

rawValue 到底是什么?

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

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 的。

3. 有关联值的 Enum

enum ScoreWithAssociatedValue {
    case Ag
    case Bg
    case Cg
    case Dg(grade: String)
}

4.总结

  • 有关联值的Enum 是没有对应的关联类,因为关联值的存在,所以不能统一关联类型。
  • 没有关联类型,也就没有实现RawRepresentable , 相应的也就没有了 rawValue

那如何实现类似的功能呢?

/// Extension
extension ScoreWithAssociatedValue {
     var rawDescription: String {
        switch self {
        case .Ag:
            return "Ag"
        case .Dg(_):
            return "Dg"
        default:
            return "Other"
        }
    }
}

ScoreWithAssociatedValue.Dg(grade: " ").rawDescription. //  Dg
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章