簡體   English   中英

擴展Protocol屬性以在Swift中提供默認實現

[英]Extending a Protocol property to provide a default implementation in Swift

我有一個協議,我用於幾個枚舉,其中包括Swift 4.2的CaseIterable

    public protocol CycleValue: CaseIterable {

  /// Computed property that returns the next value of the property.
  var nextValue:Self { get }
}

我的CycleValue用例之一是使用Theme屬性:

@objc public enum AppThemeAttributes: CycleValue  {

  case classic, darkMode // etc.

  public var nextValue: AppThemeAttributes {
    guard self != AppThemeAttributes.allCases.last else {
      return AppThemeAttributes.allCases.first!
    }

    return AppThemeAttributes(rawValue: self.rawValue + 1)!
  }
}

我有其他用例; 例如,按鈕類型。 CaseIterable使nextValue的實現變得容易,但對於所有類型的CycleValue都是一樣的。

我想實現CycleValue的擴展,它為nextValue屬性提供默認實現,並避免重復代碼(即:DRY!)。

我一直在努力使用PAT(協議相關類型)。 似乎無法使語法正確。

它應該是可能的,對嗎? 如何為nextValue提供默認實現以避免重復ode?

一種可能的解決方案是在allCases集合中定位當前值,並返回下一個元素(或環繞到第一個元素):

public protocol CycleValue: CaseIterable, Equatable {
    var nextValue: Self { get }
}

public extension CycleValue {
    var nextValue: Self {
        var idx = Self.allCases.index(of: self)!
        Self.allCases.formIndex(after: &idx)
        return idx == Self.allCases.endIndex ? Self.allCases.first! : Self.allCases[idx]
    }
}

(請注意,兩個強制解包都是安全的!) 示例:

public enum AppThemeAttributes: CycleValue  {
    case classic, darkMode // etc.
}

let a = AppThemeAttributes.classic
print(a) // classic
let b = a.nextValue
print(b) // darkMode
let c = b.nextValue
print(c) // classic

協議必須符合Equatable才能編譯,但這不是一個真正的限制: CaseIterable協議不能有關聯的值,因此編譯器總是可以合成Equatable一致性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM