繁体   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