【问题标题】:How to extend a protocol adding a computed static var如何扩展添加计算静态变量的协议
【发布时间】:2020-10-18 05:44:12
【问题描述】:

我想扩展 CaseIterable 协议,以便所有 CaseIterable 枚举都有一个 random 静态变量,它返回一个随机案例。这是我试过的代码

public extension CaseIterable {
    static var random<T: CaseIterable>: T {
        let allCases = self.allCases
        return allCases[Int.random(n: allCases.count)]
    }
}

但这无法编译。有没有办法使用静态变量来实现这一点?或者如果没有,我将如何编写等效的静态函数?

ps 任何在家玩的人的 Int.random 扩展:

public extension Int {
    static func random(n: Int) -> Int {
        return Int(arc4random_uniform(UInt32(n)))
    }
}

【问题讨论】:

    标签: swift


    【解决方案1】:

    您不能在计算属性上创建泛型类型。无需随机化索引。可以使用Collection的randomElement方法返回一个随机大小写,返回Self

    public extension CaseIterable {
        static var random: Self { allCases.randomElement()! }
    }
    

    游乐场测试:

    enum Test: String, CaseIterable {
        case a, b, c, d, e
    }
    
    let test: Test = .random  // d
    

    如果您想返回一个随机值,您可以将Self 限制为RawRepresentable 并返回RawValue

    public extension CaseIterable where Self: RawRepresentable {
        static var randomValue: RawValue { allCases.randomElement()!.rawValue }
    }
    

    enum Test: String, CaseIterable {
        case a, b, c, d, e
    }
    

    let test = Test.randomValue   // "c"
    

    【讨论】:

      【解决方案2】:

      您实际上可以在CaseIterable 扩展中直接使用randomElement

      public extension CaseIterable {
          static var random: Self {
              allCases.randomElement()!
          }
      }
      

      【讨论】:

        【解决方案3】:

        关于如何修复它,现有的答案是正确的,但理解原因可能同样有用。这不是你想的那样:

        public extension CaseIterable {
            static var random<T: CaseIterable>: T {
                // ...
            }
        }
        

        这定义了一个属性random,它将返回一个T 类型的值,它是调用者选择的任何符合CaseIterable 的类型。例如,根据这个定义,我可以进行如下调用:

        let direction: LayoutDirection = Axis.random
        

        在这种情况下,Axis 承诺它将返回一个LayoutDirection,因为这是调用者传递的T。显然这不是你想要的。您的意思是,每个 CaseIterable 都可以返回其 自己的 类型的随机值,并且正如另一个答案所示,您可以使用 static var random: Self 来做到这一点。

        泛型类型参数(如本例中的T)是参数。它们由调用者传递,而不是由实现者选择。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-09-04
          • 2016-04-18
          • 2016-01-27
          • 1970-01-01
          • 2015-12-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多