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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章