我可以创建一个限制在Swift中的某些值的数字类型吗?

时间:2018-03-14 20:41:00

标签: swift types range

我想知道是否有办法指定一个约束为Range或ClosedRange值的数字类型。

非编译示例:

typealias QuarterNumber = 1...4
typealias VolumeLevel = 0...11
typealias ObtuseAngle = 90.0<..<180.0

现在,对于第一个例子,我可能会创建类似的东西:

enum QuarterNumber : Int {
   case First = 1
   case Second = 2
   case Third = 3 
   case Fourth = 4
}

然而,在VolumeLevel我绝对想要使用原始数字的情况下,这变得笨拙。在ObtuseAngle情况下,指定它可能需要的所有单个值是完全不切实际的。

1 个答案:

答案 0 :(得分:2)

我可能采用的一种方法是使用包装类型:

struct ObtuseAngle {
    var value: Double
}

extension ObtuseAngle : ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral {
  init(floatLiteral v: FloatLiteralType) {
    guard 90.0 < v && v < 180.0 else {
      preconditionFailure("Invalid angle")
    }
    self.init(value: v)
  }
  init(integerLiteral v: IntegerLiteralType) {
    self.init(floatLiteral: Double(v))
  }
}

let x: ObtuseAngle = 115    // works
let y: ObtuseAngle = 45     // runtime crash

缺点是现在实际值隐藏在.value中,而不是更“原始”的类型。我也失去了我在“基础”类型上所有的数学运算符,但这有点意义,因为例如添加时,两个钝角可能不是钝角,并且将它们相乘不会真正产生角度类型等。

请注意,在此示例中,使用类型Measurement<UnitAngle>声明值并将其初始化为Measurement(value: v, unit: UnitAngle.degrees)也可能是合适的。