【问题标题】:Defining a Swift Protocol for Arbitrary, Int-based Enums为任意、基于 Int 的枚举定义 Swift 协议
【发布时间】:2015-11-07 03:04:56
【问题描述】:

我有这个表示颜色的枚举,并且我添加了几种方法来方便地根据原始值的算术运算获得新实例:

enum Color : Int
{
    case Red = 0
    case Green
    case Blue

    case Cyan
    case Magenta
    case Yellow


    static func random() -> Color
    {
        return Color(rawValue: Int(arc4random_uniform(6)))!
    }

    func shifted(by offset:Int) -> Color
    {
        return Color(rawValue: (self.rawValue + offset) % 6)!
        // Cyclic: wraps around
    }
}

(这让人想起旧的枚举只是 int 常量)

问题是,我还有其他几个基于 int 的枚举,我想在其中引入类似的功能,但不重复代码。

我想我应该在RawRepresentable 上定义一个协议扩展,其中RawValue == Int

extension RawRepresentable where RawValue == Int
{

...但这就是我对语法的理解结束的地方。

理想情况下,我希望需要一个返回案例数量的静态方法,并提供上面考虑到这一点的random()shifted(_:) 的默认实现(而不是这里的硬编码6)。

结论:我接受了the answer by Zoff Dino。尽管the answer given by Rob Napier 正是我所要求的,但事实证明我所要求的毕竟不是最优雅的设计,而另一个答案表明了一种更好的方法。不过,我对这两个答案都投了赞成票。谢谢大家。

【问题讨论】:

    标签: swift enums protocols rawrepresentable


    【解决方案1】:

    您应该扩展您的自定义协议而不是 RawRepresentable。试试这个:

    protocol MyProtocol {
        static var maxRawValue : Int { get }
    
        static func random() ->  Self
        func shifted(by offset: Int) -> Self
    }
    
    enum Color : Int, MyProtocol
    {
        case Red = 0
        case Green
        case Blue
    
        case Cyan
        case Magenta
        case Yellow
    
        // The maximum value of your Int enum
        static var maxRawValue: Int {
            return Yellow.rawValue
        }
    }
    
    extension MyProtocol where Self: RawRepresentable, Self.RawValue == Int {
        static func random() -> Self {
            let random = Int(arc4random_uniform(UInt32(Self.maxRawValue + 1)))
            return Self(rawValue: random)!
        }
    
        func shifted(by offset: Int) -> Self {
            return Self(rawValue: (self.rawValue + offset) % (Self.maxRawValue + 1))!
        }
    }
    
    let x = Color.random()
    let y = x.shifted(by: 1)
    

    【讨论】:

    • 嗯...您的解决方案似乎迫使我在我的每个enums 上定义和采用协议,但它的好处是不会污染所有基于 int 的枚举,对吧?我想这是更明智的解决方案,因为它不依赖于放置在某处的某些扩展,并使我的枚举更加独立和明确。否则,罗布斯的答案似乎更简单……
    • 您可以将我的答案与 Nate Cook 的案例计数代码结合起来,以使其更简单。是的,我只喜欢我选择拥有这些方法的枚举。看到random 出现在NSRegularExpressionOptions 上会很奇怪。
    【解决方案2】:

    你快到了。您只需要来自https://stackoverflow.com/a/27094913/97337 的 Nate Cook 的计案代码。

    extension RawRepresentable where RawValue == Int {
        // See http://natecook.com/blog/2014/10/loopy-random-enum-ideas/
        static var caseCount: Int {
            var max: Int = 0
            while let _ = self.init(rawValue: ++max) {}
            return max
        }
    
        static func random() -> Self {
            return Self(rawValue: Int(arc4random_uniform(UInt32(caseCount))))!
        }
    
        func shifted(by offset:Int) -> Self {
            return Self(rawValue: (self.rawValue + offset) % self.dynamicType.caseCount)!
            // Cyclic: wraps around
        }
    }
    

    【讨论】:

    • 我喜欢你通过尝试init?(rawValue:) 直到失败(因为传递的整数太大)来计算案例数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    相关资源
    最近更新 更多