【问题标题】:Nested enums to allow multiples of timeframes嵌套枚举以允许多个时间范围
【发布时间】:2023-03-29 09:25:02
【问题描述】:

我希望实现某种风格的枚举语法/功能,但我不确定如何实现。目前我有以下:

internal enum Timeframe: Equatable {

    // MARK: - Cases

    case hour(count: Int)
    case day(count: Int)
    case week(count: Int)
    case month(count: Int)
    case year(count: Int)
    case all
    case exact(date: Date)
    case unspecified
}

我想消除与计数相关的值,除非它是必需的。例如:

let oneDayTimeframe: Timeframe = .day
let twoDayTimeframe: Timeframe = .day.multiplied(by: 2)

这可能吗?即使没有办法完全实现我正在寻找的东西,我也会感谢有关潜在改进的建议。在大多数情况下,我最终使用 (count: 1),这似乎有点冗长。如果默认值可与关联值一起使用,我会使用

case hour(count: Int = 1)

有什么建议吗?

【问题讨论】:

  • 您应该重载* 运算符,而不是使用乘法函数。

标签: swift enums associated-value


【解决方案1】:

对您提供的答案进行一些迭代:

enum TimeFrame: Equatable {

    case all
    case countable(timeFrame: CountableTimeFrame)
    case exact(date: Date)
}

enum CountableTimeFrame: Equatable {

    case hour
    case day
    case week
    case month
    case year

    indirect case multiple(CountableTimeFrame, Int)

    var timeFrame: TimeFrame {
        return .countable(timeFrame: self)
    }

    static func * (left: CountableTimeFrame, right: Int) -> CountableTimeFrame {
        switch left {
        case .multiple(let timeFrame, let count):
            return .multiple(timeFrame, count * right)
        default:
            return .multiple(left, right)
        }
    }

    static func * (left: Int, right: CountableTimeFrame) -> CountableTimeFrame {
        return right * left
    }
}

不允许滥用,例如不允许:

let timeFrame: TimeFrame = .multiple(.exact(date: someDate), 666)
let timeFrame: TimeFrame = .multiple(unspecified, 40)
let timeFrame: TimeFrame = .multiple(all, -1) 

并允许使用 * 运算符进行乘法,例如

let timeFrame: CountableTimeFrame = 4 * .hour
print(timeFrame) // multiple(__lldb_expr_5.CountableTimeFrame.hour, 4)
print(timeFrame * 2) // multiple(__lldb_expr_5.CountableTimeFrame.hour, 8)

还有 .unspecified:

let optionalTimeFrame: TimeFrame? = nil

【讨论】:

  • 谢谢!我真的很喜欢这个解决方案。很遗憾,您失去了使用 TimeFrame.day 创建单一时间框架的能力,但总体而言绝对是一个更强大的实现。
【解决方案2】:

我发现使用递归枚举可以做到这一点。虽然和我建议的不完全一样,但也达到了类似的结果:

internal enum Timeframe: Equatable {

    // MARK: - Cases

    case hour
    case day
    case week
    case month
    case year
    case all
    case exact(date: Date)
    case unspecified

    // MARK: - Indirect Cases

    indirect case multiple(Timeframe, Int)
}

【讨论】:

  • 一个缺点和枚举的结构方式是 .multiple(.exact(date: someDate), 666) 或 .multiple(unspecified, 40) 或 .multiple(all, -1 ) 会编译只是罚款,但根本没有意义。
猜你喜欢
  • 2021-08-30
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多